From 3619fadf572c20bd4680da9bd6cd79e88832422a Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 1 Mar 2023 14:04:59 +0800 Subject: [PATCH 001/117] chore: add edit / create field test --- .../TestApiButton/DatabaseTestHelper.ts | 18 ++ .../components/TestApiButton/TestAPI.tsx | 12 +- .../components/TestApiButton/TestGrid.tsx | 58 ++++++ .../effects/database/cell/data_parser.ts | 3 +- .../effects/database/field/field_bd_svc.ts | 3 +- .../database/field/field_controller.ts | 6 +- .../effects/database/field/field_observer.ts | 46 ++++- .../field/type_option/type_option_bd_svc.ts | 38 ++++ .../field/type_option/type_option_context.ts | 193 ++++++++++++++++++ .../type_option/type_option_controller.ts | 113 ++++++++++ 10 files changed, 478 insertions(+), 12 deletions(-) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_bd_svc.ts create mode 100644 frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts create mode 100644 frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts index f04b9d7b41..a3163c479d 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts @@ -13,6 +13,8 @@ import { } from '../../stores/effects/database/cell/controller_builder'; import assert from 'assert'; import { None, Option, Some } from 'ts-results'; +import { TypeOptionBackendService } from '../../stores/effects/database/field/type_option/type_option_bd_svc'; +import { DatabaseBackendService } from '../../stores/effects/database/database_bd_svc'; // Create a database view for specific layout type // Do not use it production code. Just for testing @@ -104,3 +106,19 @@ export async function makeCellControllerBuilder( return None; } + +export async function assertFieldName(viewId: string, fieldId: string, fieldType: FieldType, expected: string) { + const svc = new TypeOptionBackendService(viewId); + const typeOptionPB = await svc.getTypeOption(fieldId, fieldType).then((result) => result.unwrap()); + if (typeOptionPB.field.name !== expected) { + throw Error(); + } +} + +export async function assertNumberOfFields(viewId: string, expected: number) { + const svc = new DatabaseBackendService(viewId); + const databasePB = await svc.openDatabase().then((result) => result.unwrap()); + if (databasePB.fields.length !== expected) { + throw Error(); + } +} diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx index 9a3098f601..fa7255df9c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx @@ -1,6 +1,13 @@ import React from 'react'; import TestApiButton from './TestApiButton'; -import { TestCreateGrid, TestCreateSelectOption, TestEditCell } from './TestGrid'; +import { + TestCreateGrid, + TestCreateNewField, + TestCreateSelectOption, + TestDeleteField, + TestEditCell, + TestEditField, +} from './TestGrid'; export const TestAPI = () => { return ( @@ -10,6 +17,9 @@ export const TestAPI = () => { + + + {/**/} ); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx index 58fc8497ad..f2644576a9 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx @@ -2,6 +2,8 @@ import React from 'react'; import { SelectOptionCellDataPB, ViewLayoutTypePB } from '../../../services/backend'; import { Log } from '../../utils/log'; import { + assertFieldName, + assertNumberOfFields, assertTextCell, createTestDatabaseView, editTextCell, @@ -10,6 +12,9 @@ import { } from './DatabaseTestHelper'; import assert from 'assert'; import { SelectOptionBackendService } from '../../stores/effects/database/cell/select_option_bd_svc'; +import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller'; +import { None, Some } from 'ts-results'; +import { TypeOptionBackendService } from '../../stores/effects/database/field/type_option/type_option_bd_svc'; export const TestCreateGrid = () => { async function createBuildInGrid() { @@ -80,6 +85,59 @@ export const TestCreateSelectOption = () => { return TestButton('Test create a select option', testCreateOption); }; +export const TestEditField = () => { + async function testEditField() { + const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const databaseController = await openTestDatabase(view.id); + await databaseController.open().then((result) => result.unwrap()); + const fieldInfos = databaseController.fieldController.fieldInfos; + + // Modify the name of the field + const firstFieldInfo = fieldInfos[0]; + const controller = new TypeOptionController(view.id, Some(firstFieldInfo)); + await controller.initialize(); + await controller.setFieldName('hello world'); + + await assertFieldName(view.id, firstFieldInfo.field.id, firstFieldInfo.field.field_type, 'hello world'); + } + + return TestButton('Test edit the column name', testEditField); +}; + +export const TestCreateNewField = () => { + async function testCreateNewField() { + const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const databaseController = await openTestDatabase(view.id); + await databaseController.open().then((result) => result.unwrap()); + await assertNumberOfFields(view.id, 3); + + // Modify the name of the field + const controller = new TypeOptionController(view.id, None); + await controller.initialize(); + await assertNumberOfFields(view.id, 4); + } + + return TestButton('Test create a new column', testCreateNewField); +}; + +export const TestDeleteField = () => { + async function testDeleteField() { + const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const databaseController = await openTestDatabase(view.id); + await databaseController.open().then((result) => result.unwrap()); + + // Modify the name of the field + const fieldInfo = databaseController.fieldController.fieldInfos[0]; + const controller = new TypeOptionController(view.id, Some(fieldInfo)); + await controller.initialize(); + await assertNumberOfFields(view.id, 3); + await controller.deleteField(); + await assertNumberOfFields(view.id, 2); + } + + return TestButton('Test delete a new column', testDeleteField); +}; + const TestButton = (title: string, onClick: () => void) => { return ( diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts index 836cfcadc8..0fdb978d72 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts @@ -30,7 +30,8 @@ class CellDataLoader { }; } -const utf8Decoder = new TextDecoder('utf-8'); +export const utf8Decoder = new TextDecoder('utf-8'); +export const utf8Encoder = new TextEncoder(); class StringCellDataParser extends CellDataParser { parserData(data: Uint8Array): string { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_bd_svc.ts index 835fa9ea33..f93d03d1fe 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_bd_svc.ts @@ -23,7 +23,7 @@ export class FieldBackendService { updateField = (data: { name?: string; - fieldType: FieldType; + fieldType?: FieldType; frozen?: boolean; visibility?: boolean; width?: number; @@ -65,7 +65,6 @@ export class FieldBackendService { deleteField = () => { const payload = DeleteFieldPayloadPB.fromObject({ view_id: this.viewId, field_id: this.fieldId }); - return DatabaseEventDeleteField(payload); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts index b3268e9ca9..f4aa00cd77 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts @@ -1,17 +1,17 @@ import { Log } from '../../../../utils/log'; import { DatabaseBackendService } from '../database_bd_svc'; -import { DatabaseFieldObserver } from './field_observer'; +import { DatabaseFieldChangesetObserver } from './field_observer'; import { FieldIdPB, FieldPB, IndexFieldPB } from '../../../../../services/backend/models/flowy-database/field_entities'; import { ChangeNotifier } from '../../../../utils/change_notifier'; export class FieldController { - private _fieldListener: DatabaseFieldObserver; + private _fieldListener: DatabaseFieldChangesetObserver; private _backendService: DatabaseBackendService; private _fieldNotifier = new FieldNotifier([]); constructor(public readonly viewId: string) { this._backendService = new DatabaseBackendService(viewId); - this._fieldListener = new DatabaseFieldObserver(viewId); + this._fieldListener = new DatabaseFieldChangesetObserver(viewId); this._listenOnFieldChanges(); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts index 8ae3d58249..1c77af41b0 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts @@ -1,14 +1,12 @@ -import { Err, Ok, Result } from 'ts-results'; -import { DatabaseNotification } from '../../../../../services/backend'; -import { DatabaseFieldChangesetPB } from '../../../../../services/backend/models/flowy-database/field_entities'; -import { FlowyError } from '../../../../../services/backend/models/flowy-error'; +import { Ok, Result } from 'ts-results'; +import { DatabaseNotification, DatabaseFieldChangesetPB, FlowyError, FieldPB } from '../../../../../services/backend'; import { ChangeNotifier } from '../../../../utils/change_notifier'; import { DatabaseNotificationObserver } from '../notifications/observer'; type UpdateFieldNotifiedValue = Result; export type DatabaseNotificationCallback = (value: UpdateFieldNotifiedValue) => void; -export class DatabaseFieldObserver { +export class DatabaseFieldChangesetObserver { private _notifier?: ChangeNotifier; private _listener?: DatabaseNotificationObserver; @@ -42,3 +40,41 @@ export class DatabaseFieldObserver { await this._listener?.stop(); }; } + +type FieldNotifiedValue = Result; +export type FieldNotificationCallback = (value: FieldNotifiedValue) => void; + +export class DatabaseFieldObserver { + private _notifier?: ChangeNotifier; + private _listener?: DatabaseNotificationObserver; + + constructor(public readonly fieldId: string) {} + + subscribe = (callbacks: { onFieldsChanged: FieldNotificationCallback }) => { + this._notifier = new ChangeNotifier(); + this._notifier?.observer.subscribe(callbacks.onFieldsChanged); + + this._listener = new DatabaseNotificationObserver({ + viewId: this.fieldId, + parserHandler: (notification, result) => { + switch (notification) { + case DatabaseNotification.DidUpdateField: + if (result.ok) { + this._notifier?.notify(Ok(FieldPB.deserializeBinary(result.val))); + } else { + this._notifier?.notify(result); + } + break; + default: + break; + } + }, + }); + return undefined; + }; + + unsubscribe = async () => { + this._notifier?.unsubscribe(); + await this._listener?.stop(); + }; +} diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_bd_svc.ts new file mode 100644 index 0000000000..878c0f140e --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_bd_svc.ts @@ -0,0 +1,38 @@ +import { + CreateFieldPayloadPB, + FieldType, + TypeOptionPathPB, + UpdateFieldTypePayloadPB, +} from '../../../../../../services/backend'; +import { + DatabaseEventCreateTypeOption, + DatabaseEventGetTypeOption, + DatabaseEventUpdateFieldType, +} from '../../../../../../services/backend/events/flowy-database'; + +export class TypeOptionBackendService { + constructor(public readonly viewId: string) {} + + createTypeOption = (fieldType: FieldType) => { + const payload = CreateFieldPayloadPB.fromObject({ view_id: this.viewId, field_type: fieldType }); + return DatabaseEventCreateTypeOption(payload); + }; + + getTypeOption = (fieldId: string, fieldType: FieldType) => { + const payload = TypeOptionPathPB.fromObject({ + view_id: this.viewId, + field_id: fieldId, + field_type: fieldType, + }); + return DatabaseEventGetTypeOption(payload); + }; + + updateTypeOptionType = (fieldId: string, fieldType: FieldType) => { + const payload = UpdateFieldTypePayloadPB.fromObject({ + view_id: this.viewId, + field_id: fieldId, + field_type: fieldType, + }); + return DatabaseEventUpdateFieldType(payload); + }; +} diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts new file mode 100644 index 0000000000..d8ecebc328 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts @@ -0,0 +1,193 @@ +import { None, Ok, Option, Result, Some } from 'ts-results'; +import { TypeOptionController } from './type_option_controller'; +import { + CheckboxTypeOptionPB, + ChecklistTypeOptionPB, + DateTypeOptionPB, + FlowyError, + MultiSelectTypeOptionPB, + NumberTypeOptionPB, + SingleSelectTypeOptionPB, + URLTypeOptionPB, +} from '../../../../../../services/backend'; +import { utf8Decoder, utf8Encoder } from '../../cell/data_parser'; + +abstract class TypeOptionSerde { + abstract deserialize(buffer: Uint8Array): T; + + abstract serialize(value: T): Uint8Array; +} + +// RichText +export function makeRichTextTypeOptionContext(controller: TypeOptionController): RichTextTypeOptionContext { + const parser = new RichTextTypeOptionSerde(); + return new TypeOptionContext(parser, controller); +} + +export type RichTextTypeOptionContext = TypeOptionContext; + +class RichTextTypeOptionSerde extends TypeOptionSerde { + deserialize(buffer: Uint8Array): string { + return utf8Decoder.decode(buffer); + } + + serialize(value: string): Uint8Array { + return utf8Encoder.encode(value); + } +} + +// Number +export function makeNumberTypeOptionContext(controller: TypeOptionController): NumberTypeOptionContext { + const parser = new NumberTypeOptionSerde(); + return new TypeOptionContext(parser, controller); +} + +export type NumberTypeOptionContext = TypeOptionContext; + +class NumberTypeOptionSerde extends TypeOptionSerde { + deserialize(buffer: Uint8Array): NumberTypeOptionPB { + return NumberTypeOptionPB.deserializeBinary(buffer); + } + + serialize(value: NumberTypeOptionPB): Uint8Array { + return value.serializeBinary(); + } +} + +// Checkbox +export function makeCheckboxTypeOptionContext(controller: TypeOptionController): CheckboxTypeOptionContext { + const parser = new CheckboxTypeOptionSerde(); + return new TypeOptionContext(parser, controller); +} + +export type CheckboxTypeOptionContext = TypeOptionContext; + +class CheckboxTypeOptionSerde extends TypeOptionSerde { + deserialize(buffer: Uint8Array): CheckboxTypeOptionPB { + return CheckboxTypeOptionPB.deserializeBinary(buffer); + } + + serialize(value: CheckboxTypeOptionPB): Uint8Array { + return value.serializeBinary(); + } +} + +// URL +export function makeURLTypeOptionContext(controller: TypeOptionController): URLTypeOptionContext { + const parser = new URLTypeOptionSerde(); + return new TypeOptionContext(parser, controller); +} + +export type URLTypeOptionContext = TypeOptionContext; + +class URLTypeOptionSerde extends TypeOptionSerde { + deserialize(buffer: Uint8Array): URLTypeOptionPB { + return URLTypeOptionPB.deserializeBinary(buffer); + } + + serialize(value: URLTypeOptionPB): Uint8Array { + return value.serializeBinary(); + } +} + +// Date +export function makeDateTypeOptionContext(controller: TypeOptionController): DateTypeOptionContext { + const parser = new DateTypeOptionSerde(); + return new TypeOptionContext(parser, controller); +} + +export type DateTypeOptionContext = TypeOptionContext; + +class DateTypeOptionSerde extends TypeOptionSerde { + deserialize(buffer: Uint8Array): DateTypeOptionPB { + return DateTypeOptionPB.deserializeBinary(buffer); + } + + serialize(value: DateTypeOptionPB): Uint8Array { + return value.serializeBinary(); + } +} + +// SingleSelect +export function makeSingleSelectTypeOptionContext(controller: TypeOptionController): SingleSelectTypeOptionContext { + const parser = new SingleSelectTypeOptionSerde(); + return new TypeOptionContext(parser, controller); +} + +export type SingleSelectTypeOptionContext = TypeOptionContext; + +class SingleSelectTypeOptionSerde extends TypeOptionSerde { + deserialize(buffer: Uint8Array): SingleSelectTypeOptionPB { + return SingleSelectTypeOptionPB.deserializeBinary(buffer); + } + + serialize(value: SingleSelectTypeOptionPB): Uint8Array { + return value.serializeBinary(); + } +} + +// Multi-select +export function makeMultiSelectTypeOptionContext(controller: TypeOptionController): MultiSelectTypeOptionContext { + const parser = new MultiSelectTypeOptionSerde(); + return new TypeOptionContext(parser, controller); +} + +export type MultiSelectTypeOptionContext = TypeOptionContext; + +class MultiSelectTypeOptionSerde extends TypeOptionSerde { + deserialize(buffer: Uint8Array): MultiSelectTypeOptionPB { + return MultiSelectTypeOptionPB.deserializeBinary(buffer); + } + + serialize(value: MultiSelectTypeOptionPB): Uint8Array { + return value.serializeBinary(); + } +} + +// Checklist +export function makeChecklistTypeOptionContext(controller: TypeOptionController): ChecklistTypeOptionContext { + const parser = new ChecklistTypeOptionSerde(); + return new TypeOptionContext(parser, controller); +} + +export type ChecklistTypeOptionContext = TypeOptionContext; + +class ChecklistTypeOptionSerde extends TypeOptionSerde { + deserialize(buffer: Uint8Array): ChecklistTypeOptionPB { + return ChecklistTypeOptionPB.deserializeBinary(buffer); + } + + serialize(value: ChecklistTypeOptionPB): Uint8Array { + return value.serializeBinary(); + } +} + +export class TypeOptionContext { + private typeOption: Option; + + constructor(public readonly parser: TypeOptionSerde, private readonly controller: TypeOptionController) { + this.typeOption = None; + } + + get viewId(): string { + return this.controller.viewId; + } + + getTypeOption = async (): Promise> => { + if (this.typeOption.some) { + return Ok(this.typeOption.val); + } + + const result = await this.controller.getTypeOption(); + if (result.ok) { + return Ok(this.parser.deserialize(result.val.type_option_data)); + } else { + return result; + } + }; + + setTypeOption = (typeOption: T) => { + this.controller.typeOption = this.parser.serialize(typeOption); + this.typeOption = Some(typeOption); + }; +} diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts new file mode 100644 index 0000000000..3fc393a457 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts @@ -0,0 +1,113 @@ +import { FieldPB, FieldType, TypeOptionPB } from '../../../../../../services/backend'; +import { ChangeNotifier } from '../../../../../utils/change_notifier'; +import { FieldBackendService } from '../field_bd_svc'; +import { Log } from '../../../../../utils/log'; +import { None, Option, Some } from 'ts-results'; +import { FieldInfo } from '../field_controller'; +import { TypeOptionBackendService } from './type_option_bd_svc'; + +export class TypeOptionController { + private fieldNotifier = new ChangeNotifier(); + private typeOptionData: Option; + private fieldBackendSvc?: FieldBackendService; + private typeOptionBackendSvc: TypeOptionBackendService; + + // Must call [initialize] if the passed-in fieldInfo is None + constructor(public readonly viewId: string, private initialFieldInfo: Option = None) { + this.typeOptionData = None; + this.typeOptionBackendSvc = new TypeOptionBackendService(viewId); + } + + initialize = async () => { + if (this.initialFieldInfo.none) { + await this.createTypeOption(); + } else { + await this.getTypeOption(); + } + }; + + get fieldId(): string { + return this.getFieldInfo().field.id; + } + + get fieldType(): FieldType { + return this.getFieldInfo().field.field_type; + } + + getFieldInfo = (): FieldInfo => { + if (this.typeOptionData.none) { + if (this.initialFieldInfo.some) { + return this.initialFieldInfo.val; + } else { + throw Error('Unexpect empty type option data. Should call initialize first'); + } + } + return new FieldInfo(this.typeOptionData.val.field); + }; + + switchToField = (fieldType: FieldType) => { + return this.typeOptionBackendSvc.updateTypeOptionType(this.fieldId, fieldType); + }; + + setFieldName = async (name: string) => { + if (this.typeOptionData.some) { + this.typeOptionData.val.field.name = name; + void this.fieldBackendSvc?.updateField({ name: name }); + this.fieldNotifier.notify(this.typeOptionData.val.field); + } else { + throw Error('Unexpect empty type option data. Should call initialize first'); + } + }; + + set typeOption(data: Uint8Array) { + if (this.typeOptionData.some) { + this.typeOptionData.val.type_option_data = data; + void this.fieldBackendSvc?.updateTypeOption(data).then((result) => { + if (result.err) { + Log.error(result.val); + } + }); + } else { + throw Error('Unexpect empty type option data. Should call initialize first'); + } + } + + deleteField = async () => { + if (this.fieldBackendSvc === undefined) { + Log.error('Unexpect empty field backend service'); + } + return this.fieldBackendSvc?.deleteField(); + }; + + duplicateField = async () => { + if (this.fieldBackendSvc === undefined) { + Log.error('Unexpect empty field backend service'); + } + return this.fieldBackendSvc?.duplicateField(); + }; + + // Returns the type option for specific field with specific fieldType + getTypeOption = async () => { + return this.typeOptionBackendSvc.getTypeOption(this.fieldId, this.fieldType).then((result) => { + if (result.ok) { + this.updateTypeOptionData(result.val); + } + return result; + }); + }; + + private createTypeOption = (fieldType: FieldType = FieldType.RichText) => { + return this.typeOptionBackendSvc.createTypeOption(fieldType).then((result) => { + if (result.ok) { + this.updateTypeOptionData(result.val); + } + return result; + }); + }; + + private updateTypeOptionData = (typeOptionData: TypeOptionPB) => { + this.typeOptionData = Some(typeOptionData); + this.fieldBackendSvc = new FieldBackendService(this.viewId, typeOptionData.field.id); + this.fieldNotifier.notify(typeOptionData.field); + }; +} From a3f4dfacba302d3344fb343c40beca83a8579838 Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 1 Mar 2023 14:17:17 +0800 Subject: [PATCH 002/117] chore: add delete field test --- .../components/TestApiButton/TestAPI.tsx | 2 +- .../components/TestApiButton/TestGrid.tsx | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx index fa7255df9c..9f653f9adc 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx @@ -19,7 +19,7 @@ export const TestAPI = () => { - {/**/} + ); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx index f2644576a9..c3d2859809 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx @@ -25,10 +25,14 @@ export const TestCreateGrid = () => { Log.debug('Did receive database:' + databasePB); }, onRowsChanged: async (rows) => { - assert(rows.length === 3); + if (rows.length !== 3) { + throw Error(); + } }, onFieldsChanged: (fields) => { - assert(fields.length === 3); + if (fields.length !== 3) { + throw Error(); + } }, }); await databaseController.open().then((result) => result.unwrap()); @@ -96,9 +100,10 @@ export const TestEditField = () => { const firstFieldInfo = fieldInfos[0]; const controller = new TypeOptionController(view.id, Some(firstFieldInfo)); await controller.initialize(); - await controller.setFieldName('hello world'); + const newName = 'hello world'; + await controller.setFieldName(newName); - await assertFieldName(view.id, firstFieldInfo.field.id, firstFieldInfo.field.field_type, 'hello world'); + await assertFieldName(view.id, firstFieldInfo.field.id, firstFieldInfo.field.field_type, newName); } return TestButton('Test edit the column name', testEditField); @@ -126,8 +131,10 @@ export const TestDeleteField = () => { const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); - // Modify the name of the field - const fieldInfo = databaseController.fieldController.fieldInfos[0]; + // Modify the name of the field. + // The fieldInfos[0] is the primary field by default, we can't delete it. + // So let choose the second fieldInfo. + const fieldInfo = databaseController.fieldController.fieldInfos[1]; const controller = new TypeOptionController(view.id, Some(fieldInfo)); await controller.initialize(); await assertNumberOfFields(view.id, 3); From e5a1bd2c525ae7bc60a4d98fa7dde13274b027bf Mon Sep 17 00:00:00 2001 From: ascarbek Date: Wed, 1 Mar 2023 16:04:51 +0600 Subject: [PATCH 003/117] chore: change log class arguments --- .../src/appflowy_app/utils/log.ts | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/utils/log.ts b/frontend/appflowy_tauri/src/appflowy_app/utils/log.ts index f695260397..8b6437eabb 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/utils/log.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/utils/log.ts @@ -1,21 +1,20 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ export class Log { - static error(msg?: any) { - console.log(msg); + static error(...msg: unknown[]) { + console.log(...msg); } - static info(msg?: any) { - console.log(msg); + static info(...msg: unknown[]) { + console.log(...msg); } - static debug(msg?: any) { - console.log(msg); + static debug(...msg: unknown[]) { + console.log(...msg); } - static trace(msg?: any) { - console.log(msg); + static trace(...msg: unknown[]) { + console.log(...msg); } - static warn(msg?: any) { - console.log(msg); + static warn(...msg: unknown[]) { + console.log(...msg); } } From c74308999d9410a60f1ff2e368bb839e3f000766 Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 1 Mar 2023 16:02:49 +0800 Subject: [PATCH 004/117] chore: delete/create row --- .../appflowy_tauri/src-tauri/src/request.rs | 1 - .../TestApiButton/DatabaseTestHelper.ts | 14 ++- .../components/TestApiButton/TestAPI.tsx | 4 + .../components/TestApiButton/TestGrid.tsx | 97 +++++++++++++------ .../effects/database/cell/cell_cache.ts | 26 +++-- .../effects/database/cell/cell_controller.ts | 38 ++++---- .../effects/database/cell/cell_observer.ts | 4 +- .../effects/database/database_bd_svc.ts | 3 +- .../effects/database/database_controller.ts | 12 ++- .../database/field/field_controller.ts | 36 ++++--- .../effects/database/field/field_observer.ts | 26 ++--- .../database/notifications/observer.ts | 3 +- .../stores/effects/database/row/row_bd_svc.ts | 32 ++++++ .../database/view/database_view_cache.ts | 43 ++++---- .../database/view/view_row_observer.ts | 43 ++++---- .../stores/effects/folder/app/app_observer.ts | 7 +- .../effects/folder/view/view_observer.ts | 4 +- .../folder/workspace/workspace_observer.ts | 33 ++++--- .../src/ts_event/event_template.tera | 6 +- .../src/entities/row_entities.rs | 2 +- 20 files changed, 262 insertions(+), 172 deletions(-) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_bd_svc.ts diff --git a/frontend/appflowy_tauri/src-tauri/src/request.rs b/frontend/appflowy_tauri/src-tauri/src/request.rs index 0e00342782..4f88885a51 100644 --- a/frontend/appflowy_tauri/src-tauri/src/request.rs +++ b/frontend/appflowy_tauri/src-tauri/src/request.rs @@ -32,7 +32,6 @@ impl std::convert::From for AFTauriResponse { } // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command -#[tracing::instrument(level = "trace", skip(app_handler))] #[tauri::command] pub async fn invoke_request( request: AFTauriRequest, diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts index a3163c479d..4a79bc16e0 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts @@ -35,7 +35,7 @@ export async function assertTextCell(rowInfo: RowInfo, databaseController: Datab onCellChanged: (value) => { const cellContent = value.unwrap(); if (cellContent !== expectedContent) { - throw Error(); + throw Error('Text cell content is not match'); } }, }); @@ -111,7 +111,7 @@ export async function assertFieldName(viewId: string, fieldId: string, fieldType const svc = new TypeOptionBackendService(viewId); const typeOptionPB = await svc.getTypeOption(fieldId, fieldType).then((result) => result.unwrap()); if (typeOptionPB.field.name !== expected) { - throw Error(); + throw Error('Expect field name:' + expected + 'but receive:' + typeOptionPB.field.name); } } @@ -119,6 +119,14 @@ export async function assertNumberOfFields(viewId: string, expected: number) { const svc = new DatabaseBackendService(viewId); const databasePB = await svc.openDatabase().then((result) => result.unwrap()); if (databasePB.fields.length !== expected) { - throw Error(); + throw Error('Expect number of fields:' + expected + 'but receive:' + databasePB.fields.length); + } +} + +export async function assertNumberOfRows(viewId: string, expected: number) { + const svc = new DatabaseBackendService(viewId); + const databasePB = await svc.openDatabase().then((result) => result.unwrap()); + if (databasePB.rows.length !== expected) { + throw Error('Expect number of rows:' + expected + 'but receive:' + databasePB.rows.length); } } diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx index 9f653f9adc..a9ee26b174 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx @@ -3,8 +3,10 @@ import TestApiButton from './TestApiButton'; import { TestCreateGrid, TestCreateNewField, + TestCreateRow, TestCreateSelectOption, TestDeleteField, + TestDeleteRow, TestEditCell, TestEditField, } from './TestGrid'; @@ -15,6 +17,8 @@ export const TestAPI = () => {
    + + diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx index c3d2859809..b303d9a824 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx @@ -4,6 +4,7 @@ import { Log } from '../../utils/log'; import { assertFieldName, assertNumberOfFields, + assertNumberOfRows, assertTextCell, createTestDatabaseView, editTextCell, @@ -15,6 +16,7 @@ import { SelectOptionBackendService } from '../../stores/effects/database/cell/s import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller'; import { None, Some } from 'ts-results'; import { TypeOptionBackendService } from '../../stores/effects/database/field/type_option/type_option_bd_svc'; +import { RowBackendService } from '../../stores/effects/database/row/row_bd_svc'; export const TestCreateGrid = () => { async function createBuildInGrid() { @@ -26,12 +28,12 @@ export const TestCreateGrid = () => { }, onRowsChanged: async (rows) => { if (rows.length !== 3) { - throw Error(); + throw Error('Expected number of rows is 3, but receive ' + rows.length); } }, onFieldsChanged: (fields) => { if (fields.length !== 3) { - throw Error(); + throw Error('Expected number of fields is 3, but receive ' + fields.length); } }, }); @@ -45,45 +47,77 @@ export const TestEditCell = () => { async function testGridRow() { const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); const databaseController = await openTestDatabase(view.id); - databaseController.subscribe({ - onRowsChanged: async (rows) => { - for (const [index, row] of rows.entries()) { - const cellContent = index.toString(); - await editTextCell(row, databaseController, cellContent); - await assertTextCell(row, databaseController, cellContent); - } - }, - }); await databaseController.open().then((result) => result.unwrap()); + + for (const [index, row] of databaseController.databaseViewCache.rowInfos.entries()) { + const cellContent = index.toString(); + await editTextCell(row, databaseController, cellContent); + await assertTextCell(row, databaseController, cellContent); + } } return TestButton('Test editing cell', testGridRow); }; +export const TestCreateRow = () => { + async function testCreateRow() { + const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const databaseController = await openTestDatabase(view.id); + await databaseController.open().then((result) => result.unwrap()); + await assertNumberOfRows(view.id, 3); + + // Create a row from a DatabaseController or create using the RowBackendService + await databaseController.createRow(); + await assertNumberOfRows(view.id, 4); + await databaseController.dispose(); + } + + return TestButton('Test create row', testCreateRow); +}; +export const TestDeleteRow = () => { + async function testDeleteRow() { + const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const databaseController = await openTestDatabase(view.id); + await databaseController.open().then((result) => result.unwrap()); + + const rows = databaseController.databaseViewCache.rowInfos; + const svc = new RowBackendService(view.id); + await svc.deleteRow(rows[0].row.id); + await assertNumberOfRows(view.id, 2); + + // Wait the databaseViewCache get the change notification and + // update the rows. + await new Promise((resolve) => setTimeout(resolve, 200)); + if (databaseController.databaseViewCache.rowInfos.length !== 2) { + throw Error('The number of rows is not match'); + } + await databaseController.dispose(); + } + + return TestButton('Test delete row', testDeleteRow); +}; export const TestCreateSelectOption = () => { async function testCreateOption() { const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); const databaseController = await openTestDatabase(view.id); - databaseController.subscribe({ - onRowsChanged: async (rows) => { - for (const [index, row] of rows.entries()) { - if (index === 0) { - const cellController = await makeSingleSelectCellController(row, databaseController).then((result) => - result.unwrap() - ); - cellController.subscribeChanged({ - onCellChanged: (value) => { - const option: SelectOptionCellDataPB = value.unwrap(); - console.log(option); - }, - }); - const backendSvc = new SelectOptionBackendService(cellController.cellIdentifier); - await backendSvc.createOption({ name: 'option' + index }); - } - } - }, - }); await databaseController.open().then((result) => result.unwrap()); + for (const [index, row] of databaseController.databaseViewCache.rowInfos.entries()) { + if (index === 0) { + const cellController = await makeSingleSelectCellController(row, databaseController).then((result) => + result.unwrap() + ); + cellController.subscribeChanged({ + onCellChanged: (value) => { + const option: SelectOptionCellDataPB = value.unwrap(); + console.log(option); + }, + }); + const backendSvc = new SelectOptionBackendService(cellController.cellIdentifier); + await backendSvc.createOption({ name: 'option' + index }); + await cellController.dispose(); + } + } + await databaseController.dispose(); } return TestButton('Test create a select option', testCreateOption); @@ -104,6 +138,7 @@ export const TestEditField = () => { await controller.setFieldName(newName); await assertFieldName(view.id, firstFieldInfo.field.id, firstFieldInfo.field.field_type, newName); + await databaseController.dispose(); } return TestButton('Test edit the column name', testEditField); @@ -120,6 +155,7 @@ export const TestCreateNewField = () => { const controller = new TypeOptionController(view.id, None); await controller.initialize(); await assertNumberOfFields(view.id, 4); + await databaseController.dispose(); } return TestButton('Test create a new column', testCreateNewField); @@ -140,6 +176,7 @@ export const TestDeleteField = () => { await assertNumberOfFields(view.id, 3); await controller.deleteField(); await assertNumberOfFields(view.id, 2); + await databaseController.dispose(); } return TestButton('Test delete a new column', testDeleteField); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts index 1b6c3349d7..979a06ee0b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts @@ -5,32 +5,38 @@ export class CellCacheKey { constructor(public readonly fieldId: string, public readonly rowId: string) {} } +type CellDataByRowId = Map; + export class CellCache { - _cellDataByFieldId = new Map>(); + private cellDataByFieldId = new Map(); constructor(public readonly databaseId: string) {} remove = (key: CellCacheKey) => { - const inner = this._cellDataByFieldId.get(key.fieldId); - if (inner !== undefined) { - inner.delete(key.rowId); + const cellDataByRowId = this.cellDataByFieldId.get(key.fieldId); + if (cellDataByRowId !== undefined) { + console.log('cellDataByRowId', cellDataByRowId); + cellDataByRowId.delete(key.rowId); } }; removeWithFieldId = (fieldId: string) => { - this._cellDataByFieldId.delete(fieldId); + this.cellDataByFieldId.delete(fieldId); }; insert = (key: CellCacheKey, value: any) => { - let inner = this._cellDataByFieldId.get(key.fieldId); - if (inner === undefined) { - inner = this._cellDataByFieldId.set(key.fieldId, new Map()); + const cellDataByRowId = this.cellDataByFieldId.get(key.fieldId); + if (cellDataByRowId === undefined) { + const map = new Map(); + map.set(key.rowId, value); + this.cellDataByFieldId.set(key.fieldId, map); + } else { + cellDataByRowId.set(key.rowId, value); } - inner.set(key.rowId, value); }; get(key: CellCacheKey): Option { - const inner = this._cellDataByFieldId.get(key.fieldId); + const inner = this.cellDataByFieldId.get(key.fieldId); if (inner === undefined) { return None; } else { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts index 4d4c879194..c438cd6cc8 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts @@ -14,10 +14,10 @@ export abstract class CellFieldNotifier { } export class CellController { - private _fieldBackendService: FieldBackendService; - private _cellDataNotifier: CellDataNotifier>; - private _cellObserver: CellObserver; - private _cacheKey: CellCacheKey; + private fieldBackendService: FieldBackendService; + private cellDataNotifier: CellDataNotifier>; + private cellObserver: CellObserver; + private readonly cacheKey: CellCacheKey; constructor( public readonly cellIdentifier: CellIdentifier, @@ -26,17 +26,17 @@ export class CellController { private readonly cellDataLoader: CellDataLoader, private readonly cellDataPersistence: CellDataPersistence ) { - this._fieldBackendService = new FieldBackendService(cellIdentifier.viewId, cellIdentifier.fieldId); - this._cacheKey = new CellCacheKey(cellIdentifier.rowId, cellIdentifier.fieldId); - this._cellDataNotifier = new CellDataNotifier(cellCache.get(this._cacheKey)); - this._cellObserver = new CellObserver(cellIdentifier.rowId, cellIdentifier.fieldId); - this._cellObserver.subscribe({ + this.fieldBackendService = new FieldBackendService(cellIdentifier.viewId, cellIdentifier.fieldId); + this.cacheKey = new CellCacheKey(cellIdentifier.rowId, cellIdentifier.fieldId); + this.cellDataNotifier = new CellDataNotifier(cellCache.get(this.cacheKey)); + this.cellObserver = new CellObserver(cellIdentifier.rowId, cellIdentifier.fieldId); + void this.cellObserver.subscribe({ /// 1.Listen on user edit event and load the new cell data if needed. /// For example: /// user input: 12 /// cell display: $12 onCellChanged: async () => { - this.cellCache.remove(this._cacheKey); + this.cellCache.remove(this.cacheKey); await this._loadCellData(); }, }); @@ -55,7 +55,7 @@ export class CellController { } }); - this._cellDataNotifier.observer.subscribe((cellData) => { + this.cellDataNotifier.observer.subscribe((cellData) => { if (cellData !== null) { callbacks.onCellChanged(cellData); } @@ -63,7 +63,7 @@ export class CellController { }; getTypeOption = async

    , PD>(parser: P) => { - const result = await this._fieldBackendService.getTypeOptionData(this.cellIdentifier.fieldType); + const result = await this.fieldBackendService.getTypeOptionData(this.cellIdentifier.fieldType); if (result.ok) { return Ok(parser.fromBuffer(result.val.type_option_data)); } else { @@ -83,7 +83,7 @@ export class CellController { /// data from the backend and then the [onCellChanged] will /// get called getCellData = (): Option => { - const cellData = this.cellCache.get(this._cacheKey); + const cellData = this.cellCache.get(this.cacheKey); if (cellData.none) { void this._loadCellData(); } @@ -93,14 +93,18 @@ export class CellController { private _loadCellData = () => { return this.cellDataLoader.loadData().then((result) => { if (result.ok && result.val !== undefined) { - this.cellCache.insert(this._cacheKey, result.val); - this._cellDataNotifier.cellData = Some(result.val); + this.cellCache.insert(this.cacheKey, result.val); + this.cellDataNotifier.cellData = Some(result.val); } else { - this.cellCache.remove(this._cacheKey); - this._cellDataNotifier.cellData = None; + this.cellCache.remove(this.cacheKey); + this.cellDataNotifier.cellData = None; } }); }; + + dispose = async () => { + await this.cellObserver.unsubscribe(); + }; } export class CellFieldNotifierImpl extends CellFieldNotifier { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts index 27695a0c3c..06409c7ae2 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts @@ -13,7 +13,7 @@ export class CellObserver { constructor(public readonly rowId: string, public readonly fieldId: string) {} - subscribe = (callbacks: { onCellChanged: CellChangedCallback }) => { + subscribe = async (callbacks: { onCellChanged: CellChangedCallback }) => { this._notifier = new ChangeNotifier(); this._notifier?.observer.subscribe(callbacks.onCellChanged); @@ -33,7 +33,7 @@ export class CellObserver { } }, }); - return undefined; + await this._listener.start(); }; unsubscribe = async () => { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts index c4d1495d11..19f956564d 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts @@ -33,8 +33,7 @@ export class DatabaseBackendService { }; createRow = async (rowId?: string) => { - const props = { database_id: this.viewId, start_row_id: rowId ?? undefined }; - const payload = CreateRowPayloadPB.fromObject(props); + const payload = CreateRowPayloadPB.fromObject({ view_id: this.viewId, start_row_id: rowId ?? undefined }); return DatabaseEventCreateRow(payload); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts index 3380cffb71..25af4535ea 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts @@ -12,13 +12,13 @@ export type SubscribeCallback = { }; export class DatabaseController { - private _backendService: DatabaseBackendService; + private backendService: DatabaseBackendService; fieldController: FieldController; databaseViewCache: DatabaseViewCache; private _callback?: SubscribeCallback; constructor(public readonly viewId: string) { - this._backendService = new DatabaseBackendService(viewId); + this.backendService = new DatabaseBackendService(viewId); this.fieldController = new FieldController(viewId); this.databaseViewCache = new DatabaseViewCache(viewId, this.fieldController); } @@ -32,11 +32,13 @@ export class DatabaseController { }; open = async () => { - const result = await this._backendService.openDatabase(); + const result = await this.backendService.openDatabase(); if (result.ok) { const database: DatabasePB = result.val; this._callback?.onViewChanged?.(database); await this.fieldController.loadFields(database.fields); + await this.databaseViewCache.listenOnRowsChanged(); + await this.fieldController.listenOnFieldChanges(); this.databaseViewCache.initializeWithRows(database.rows); return Ok.EMPTY; } else { @@ -45,11 +47,11 @@ export class DatabaseController { }; createRow = async () => { - return this._backendService.createRow(); + return this.backendService.createRow(); }; dispose = async () => { - await this._backendService.closeDatabase(); + await this.backendService.closeDatabase(); await this.fieldController.dispose(); await this.databaseViewCache.dispose(); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts index f4aa00cd77..2d5a3959b2 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts @@ -5,47 +5,45 @@ import { FieldIdPB, FieldPB, IndexFieldPB } from '../../../../../services/backen import { ChangeNotifier } from '../../../../utils/change_notifier'; export class FieldController { - private _fieldListener: DatabaseFieldChangesetObserver; - private _backendService: DatabaseBackendService; - private _fieldNotifier = new FieldNotifier([]); + private fieldListener: DatabaseFieldChangesetObserver; + private backendService: DatabaseBackendService; + private fieldNotifier = new FieldNotifier([]); constructor(public readonly viewId: string) { - this._backendService = new DatabaseBackendService(viewId); - this._fieldListener = new DatabaseFieldChangesetObserver(viewId); - - this._listenOnFieldChanges(); + this.backendService = new DatabaseBackendService(viewId); + this.fieldListener = new DatabaseFieldChangesetObserver(viewId); } dispose = async () => { - this._fieldNotifier.unsubscribe(); - await this._fieldListener.unsubscribe(); + this.fieldNotifier.unsubscribe(); + await this.fieldListener.unsubscribe(); }; get fieldInfos(): readonly FieldInfo[] { - return this._fieldNotifier.fieldInfos; + return this.fieldNotifier.fieldInfos; } getField = (fieldId: string): FieldInfo | undefined => { - return this._fieldNotifier.fieldInfos.find((element) => element.field.id === fieldId); + return this.fieldNotifier.fieldInfos.find((element) => element.field.id === fieldId); }; loadFields = async (fieldIds: FieldIdPB[]) => { - const result = await this._backendService.getFields(fieldIds); + const result = await this.backendService.getFields(fieldIds); if (result.ok) { - this._fieldNotifier.fieldInfos = result.val.map((field) => new FieldInfo(field)); + this.fieldNotifier.fieldInfos = result.val.map((field) => new FieldInfo(field)); } else { Log.error(result.val); } }; subscribeOnFieldsChanged = (callback?: (fieldInfos: readonly FieldInfo[]) => void) => { - return this._fieldNotifier.observer.subscribe((fieldInfos) => { + return this.fieldNotifier.observer.subscribe((fieldInfos) => { callback?.(fieldInfos); }); }; - _listenOnFieldChanges = () => { - this._fieldListener.subscribe({ + listenOnFieldChanges = async () => { + await this.fieldListener.subscribe({ onFieldsChanged: (result) => { if (result.ok) { const changeset = result.val; @@ -70,7 +68,7 @@ export class FieldController { }; const newFieldInfos = [...this.fieldInfos]; newFieldInfos.filter(predicate); - this._fieldNotifier.fieldInfos = newFieldInfos; + this.fieldNotifier.fieldInfos = newFieldInfos; }; _insertFields = (insertedFields: IndexFieldPB[]) => { @@ -86,7 +84,7 @@ export class FieldController { newFieldInfos.push(fieldInfo); } }); - this._fieldNotifier.fieldInfos = newFieldInfos; + this.fieldNotifier.fieldInfos = newFieldInfos; }; _updateFields = (updatedFields: FieldPB[]) => { @@ -104,7 +102,7 @@ export class FieldController { } }); }); - this._fieldNotifier.fieldInfos = newFieldInfos; + this.fieldNotifier.fieldInfos = newFieldInfos; }; } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts index 1c77af41b0..423faac3db 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts @@ -7,24 +7,24 @@ type UpdateFieldNotifiedValue = Result; export type DatabaseNotificationCallback = (value: UpdateFieldNotifiedValue) => void; export class DatabaseFieldChangesetObserver { - private _notifier?: ChangeNotifier; - private _listener?: DatabaseNotificationObserver; + private notifier?: ChangeNotifier; + private listener?: DatabaseNotificationObserver; constructor(public readonly viewId: string) {} - subscribe = (callbacks: { onFieldsChanged: DatabaseNotificationCallback }) => { - this._notifier = new ChangeNotifier(); - this._notifier?.observer.subscribe(callbacks.onFieldsChanged); + subscribe = async (callbacks: { onFieldsChanged: DatabaseNotificationCallback }) => { + this.notifier = new ChangeNotifier(); + this.notifier?.observer.subscribe(callbacks.onFieldsChanged); - this._listener = new DatabaseNotificationObserver({ + this.listener = new DatabaseNotificationObserver({ viewId: this.viewId, parserHandler: (notification, result) => { switch (notification) { case DatabaseNotification.DidUpdateFields: if (result.ok) { - this._notifier?.notify(Ok(DatabaseFieldChangesetPB.deserializeBinary(result.val))); + this.notifier?.notify(Ok(DatabaseFieldChangesetPB.deserializeBinary(result.val))); } else { - this._notifier?.notify(result); + this.notifier?.notify(result); } return; default: @@ -32,12 +32,12 @@ export class DatabaseFieldChangesetObserver { } }, }); - return undefined; + await this.listener.start(); }; unsubscribe = async () => { - this._notifier?.unsubscribe(); - await this._listener?.stop(); + this.notifier?.unsubscribe(); + await this.listener?.stop(); }; } @@ -50,7 +50,7 @@ export class DatabaseFieldObserver { constructor(public readonly fieldId: string) {} - subscribe = (callbacks: { onFieldsChanged: FieldNotificationCallback }) => { + subscribe = async (callbacks: { onFieldsChanged: FieldNotificationCallback }) => { this._notifier = new ChangeNotifier(); this._notifier?.observer.subscribe(callbacks.onFieldsChanged); @@ -70,7 +70,7 @@ export class DatabaseFieldObserver { } }, }); - return undefined; + await this._listener.start(); }; unsubscribe = async () => { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts index 855c6a3ab4..186e3276b0 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts @@ -1,7 +1,6 @@ -import { DatabaseNotification } from '../../../../../services/backend'; +import { DatabaseNotification, FlowyError } from '../../../../../services/backend'; import { AFNotificationObserver } from '../../../../../services/backend/notifications'; import { DatabaseNotificationParser } from './parser'; -import { FlowyError } from '../../../../../services/backend'; import { Result } from 'ts-results'; export type ParserHandler = (notification: DatabaseNotification, result: Result) => void; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_bd_svc.ts new file mode 100644 index 0000000000..1ee9601cba --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_bd_svc.ts @@ -0,0 +1,32 @@ +import { CreateRowPayloadPB, RowIdPB } from '../../../../../services/backend'; +import { + DatabaseEventCreateRow, + DatabaseEventDeleteRow, + DatabaseEventDuplicateRow, + DatabaseEventGetRow, +} from '../../../../../services/backend/events/flowy-database'; + +export class RowBackendService { + constructor(public readonly viewId: string) {} + + // Create a row below the row with rowId + createRow = (rowId: string) => { + const payload = CreateRowPayloadPB.fromObject({ view_id: this.viewId, start_row_id: rowId }); + return DatabaseEventCreateRow(payload); + }; + + deleteRow = (rowId: string) => { + const payload = RowIdPB.fromObject({ view_id: this.viewId, row_id: rowId }); + return DatabaseEventDeleteRow(payload); + }; + + duplicateRow = (rowId: string) => { + const payload = RowIdPB.fromObject({ view_id: this.viewId, row_id: rowId }); + return DatabaseEventDuplicateRow(payload); + }; + + getRow = (rowId: string) => { + const payload = RowIdPB.fromObject({ view_id: this.viewId, row_id: rowId }); + return DatabaseEventGetRow(payload); + }; +} diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts index 1468ce3246..29b783864a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts @@ -1,63 +1,62 @@ import { DatabaseViewRowsObserver } from './view_row_observer'; -import { RowCache, RowChangedReason, RowInfo } from '../row/row_cache'; +import { RowCache, RowInfo } from '../row/row_cache'; import { FieldController } from '../field/field_controller'; -import { RowPB } from '../../../../../services/backend/models/flowy-database/row_entities'; +import { RowPB } from '../../../../../services/backend'; import { Subscription } from 'rxjs'; export class DatabaseViewCache { - private readonly _rowsObserver: DatabaseViewRowsObserver; - private readonly _rowCache: RowCache; - private readonly _fieldSubscription?: Subscription; + private readonly rowsObserver: DatabaseViewRowsObserver; + private readonly rowCache: RowCache; + private readonly fieldSubscription?: Subscription; constructor(public readonly viewId: string, fieldController: FieldController) { - this._rowsObserver = new DatabaseViewRowsObserver(viewId); - this._rowCache = new RowCache(viewId, () => fieldController.fieldInfos); - this._fieldSubscription = fieldController.subscribeOnFieldsChanged((fieldInfos) => { + this.rowsObserver = new DatabaseViewRowsObserver(viewId); + this.rowCache = new RowCache(viewId, () => fieldController.fieldInfos); + this.fieldSubscription = fieldController.subscribeOnFieldsChanged((fieldInfos) => { fieldInfos.forEach((fieldInfo) => { - this._rowCache.onFieldUpdated(fieldInfo); + this.rowCache.onFieldUpdated(fieldInfo); }); }); - this._listenOnRowsChanged(); } initializeWithRows = (rows: RowPB[]) => { - this._rowCache.initializeRows(rows); + this.rowCache.initializeRows(rows); }; get rowInfos(): readonly RowInfo[] { - return this._rowCache.rows; + return this.rowCache.rows; } getRowCache = () => { - return this._rowCache; + return this.rowCache; }; dispose = async () => { - this._fieldSubscription?.unsubscribe(); - await this._rowsObserver.unsubscribe(); - await this._rowCache.dispose(); + this.fieldSubscription?.unsubscribe(); + await this.rowsObserver.unsubscribe(); + await this.rowCache.dispose(); }; - _listenOnRowsChanged = () => { - this._rowsObserver.subscribe({ + listenOnRowsChanged = async () => { + await this.rowsObserver.subscribe({ onRowsVisibilityChanged: (result) => { if (result.ok) { - this._rowCache.applyRowsVisibility(result.val); + this.rowCache.applyRowsVisibility(result.val); } }, onNumberOfRowsChanged: (result) => { if (result.ok) { - this._rowCache.applyRowsChanged(result.val); + this.rowCache.applyRowsChanged(result.val); } }, onReorderRows: (result) => { if (result.ok) { - this._rowCache.applyReorderRows(result.val); + this.rowCache.applyReorderRows(result.val); } }, onReorderSingleRow: (result) => { if (result.ok) { - this._rowCache.applyReorderSingleRow(result.val); + this.rowCache.applyReorderSingleRow(result.val); } }, }); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts index 72e50273bf..1bc3f4de6e 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts @@ -16,26 +16,26 @@ export type ReorderRowsNotifyValue = Result; export type ReorderSingleRowNotifyValue = Result; export class DatabaseViewRowsObserver { - private _rowsVisibilityNotifier = new ChangeNotifier(); - private _rowsNotifier = new ChangeNotifier(); - private _reorderRowsNotifier = new ChangeNotifier(); - private _reorderSingleRowNotifier = new ChangeNotifier(); + private rowsVisibilityNotifier = new ChangeNotifier(); + private rowsNotifier = new ChangeNotifier(); + private reorderRowsNotifier = new ChangeNotifier(); + private reorderSingleRowNotifier = new ChangeNotifier(); private _listener?: DatabaseNotificationObserver; constructor(public readonly viewId: string) {} - subscribe = (callbacks: { + subscribe = async (callbacks: { onRowsVisibilityChanged?: (value: RowsVisibilityNotifyValue) => void; onNumberOfRowsChanged?: (value: RowsNotifyValue) => void; onReorderRows?: (value: ReorderRowsNotifyValue) => void; onReorderSingleRow?: (value: ReorderSingleRowNotifyValue) => void; }) => { // - this._rowsVisibilityNotifier.observer.subscribe(callbacks.onRowsVisibilityChanged); - this._rowsNotifier.observer.subscribe(callbacks.onNumberOfRowsChanged); - this._reorderRowsNotifier.observer.subscribe(callbacks.onReorderRows); - this._reorderSingleRowNotifier.observer.subscribe(callbacks.onReorderSingleRow); + this.rowsVisibilityNotifier.observer.subscribe(callbacks.onRowsVisibilityChanged); + this.rowsNotifier.observer.subscribe(callbacks.onNumberOfRowsChanged); + this.reorderRowsNotifier.observer.subscribe(callbacks.onReorderRows); + this.reorderSingleRowNotifier.observer.subscribe(callbacks.onReorderSingleRow); this._listener = new DatabaseNotificationObserver({ viewId: this.viewId, @@ -43,30 +43,30 @@ export class DatabaseViewRowsObserver { switch (notification) { case DatabaseNotification.DidUpdateViewRowsVisibility: if (result.ok) { - this._rowsVisibilityNotifier.notify(Ok(RowsVisibilityChangesetPB.deserializeBinary(result.val))); + this.rowsVisibilityNotifier.notify(Ok(RowsVisibilityChangesetPB.deserializeBinary(result.val))); } else { - this._rowsVisibilityNotifier.notify(result); + this.rowsVisibilityNotifier.notify(result); } break; case DatabaseNotification.DidUpdateViewRows: if (result.ok) { - this._rowsNotifier.notify(Ok(RowsChangesetPB.deserializeBinary(result.val))); + this.rowsNotifier.notify(Ok(RowsChangesetPB.deserializeBinary(result.val))); } else { - this._rowsNotifier.notify(result); + this.rowsNotifier.notify(result); } break; case DatabaseNotification.DidReorderRows: if (result.ok) { - this._reorderRowsNotifier.notify(Ok(ReorderAllRowsPB.deserializeBinary(result.val).row_orders)); + this.reorderRowsNotifier.notify(Ok(ReorderAllRowsPB.deserializeBinary(result.val).row_orders)); } else { - this._reorderRowsNotifier.notify(result); + this.reorderRowsNotifier.notify(result); } break; case DatabaseNotification.DidReorderSingleRow: if (result.ok) { - this._reorderSingleRowNotifier.notify(Ok(ReorderSingleRowPB.deserializeBinary(result.val))); + this.reorderSingleRowNotifier.notify(Ok(ReorderSingleRowPB.deserializeBinary(result.val))); } else { - this._reorderSingleRowNotifier.notify(result); + this.reorderSingleRowNotifier.notify(result); } break; default: @@ -74,13 +74,14 @@ export class DatabaseViewRowsObserver { } }, }); + await this._listener.start(); }; unsubscribe = async () => { - this._rowsVisibilityNotifier.unsubscribe(); - this._reorderRowsNotifier.unsubscribe(); - this._rowsNotifier.unsubscribe(); - this._reorderSingleRowNotifier.unsubscribe(); + this.rowsVisibilityNotifier.unsubscribe(); + this.reorderRowsNotifier.unsubscribe(); + this.rowsNotifier.unsubscribe(); + this.reorderSingleRowNotifier.unsubscribe(); await this._listener?.stop(); }; } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts index f1471a5a46..377541fc3a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/app/app_observer.ts @@ -6,15 +6,14 @@ import { FolderNotificationObserver } from '../notifications/observer'; export type AppUpdateNotifyValue = Result; export type AppUpdateNotifyCallback = (value: AppUpdateNotifyValue) => void; -export class WorkspaceObserver { +export class AppObserver { _appNotifier = new ChangeNotifier(); _listener?: FolderNotificationObserver; constructor(public readonly appId: string) {} - subscribe = (callbacks: { onAppChanged: AppUpdateNotifyCallback }) => { + subscribe = async (callbacks: { onAppChanged: AppUpdateNotifyCallback }) => { this._appNotifier?.observer.subscribe(callbacks.onAppChanged); - this._listener = new FolderNotificationObserver({ viewId: this.appId, parserHandler: (notification, result) => { @@ -31,7 +30,7 @@ export class WorkspaceObserver { } }, }); - return undefined; + await this._listener.start(); }; unsubscribe = async () => { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_observer.ts index 6fabf53a63..c820a653ef 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/view/view_observer.ts @@ -18,7 +18,7 @@ export class ViewObserver { constructor(public readonly viewId: string) {} - subscribe = (callbacks: { + subscribe = async (callbacks: { onViewUpdate?: (value: UpdateViewNotifyValue) => void; onViewDelete?: (value: DeleteViewNotifyValue) => void; onViewRestored?: (value: RestoreViewNotifyValue) => void; @@ -77,7 +77,7 @@ export class ViewObserver { } }, }); - return undefined; + await this._listener.start(); }; unsubscribe = async () => { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts index 80ea5d39b0..abcd6081d8 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/folder/workspace/workspace_observer.ts @@ -9,32 +9,35 @@ export type WorkspaceNotifyValue = Result; export type WorkspaceNotifyCallback = (value: WorkspaceNotifyValue) => void; export class WorkspaceObserver { - private _appListNotifier = new ChangeNotifier(); - private _workspaceNotifier = new ChangeNotifier(); - private _listener?: FolderNotificationObserver; + private appListNotifier = new ChangeNotifier(); + private workspaceNotifier = new ChangeNotifier(); + private listener?: FolderNotificationObserver; constructor(public readonly workspaceId: string) {} - subscribe = (callbacks: { onAppListChanged: AppListNotifyCallback; onWorkspaceChanged: WorkspaceNotifyCallback }) => { - this._appListNotifier?.observer.subscribe(callbacks.onAppListChanged); - this._workspaceNotifier?.observer.subscribe(callbacks.onWorkspaceChanged); + subscribe = async (callbacks: { + onAppListChanged: AppListNotifyCallback; + onWorkspaceChanged: WorkspaceNotifyCallback; + }) => { + this.appListNotifier?.observer.subscribe(callbacks.onAppListChanged); + this.workspaceNotifier?.observer.subscribe(callbacks.onWorkspaceChanged); - this._listener = new FolderNotificationObserver({ + this.listener = new FolderNotificationObserver({ viewId: this.workspaceId, parserHandler: (notification, result) => { switch (notification) { case FolderNotification.DidUpdateWorkspace: if (result.ok) { - this._workspaceNotifier?.notify(Ok(WorkspacePB.deserializeBinary(result.val))); + this.workspaceNotifier?.notify(Ok(WorkspacePB.deserializeBinary(result.val))); } else { - this._workspaceNotifier?.notify(result); + this.workspaceNotifier?.notify(result); } break; case FolderNotification.DidUpdateWorkspaceApps: if (result.ok) { - this._appListNotifier?.notify(Ok(RepeatedAppPB.deserializeBinary(result.val).items)); + this.appListNotifier?.notify(Ok(RepeatedAppPB.deserializeBinary(result.val).items)); } else { - this._appListNotifier?.notify(result); + this.appListNotifier?.notify(result); } break; default: @@ -42,12 +45,12 @@ export class WorkspaceObserver { } }, }); - return undefined; + await this.listener.start(); }; unsubscribe = async () => { - this._appListNotifier.unsubscribe(); - this._workspaceNotifier.unsubscribe(); - await this._listener?.stop(); + this.appListNotifier.unsubscribe(); + this.workspaceNotifier.unsubscribe(); + await this.listener?.stop(); }; } diff --git a/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera b/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera index 905c6a68b7..13c02b4763 100644 --- a/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera +++ b/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera @@ -24,14 +24,14 @@ export async function {{ event_func_name }}(): Promise for CreateRowPayloadPB { type Error = ErrorCode; fn try_into(self) -> Result { - let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::DatabaseIdIsEmpty)?; + let view_id = NotEmptyStr::parse(self.view_id).map_err(|_| ErrorCode::ViewIdIsInvalid)?; Ok(CreateRowParams { view_id: view_id.0, From fd135fb664de23e18d1f7c0cb588ab9fccc97f28 Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 1 Mar 2023 18:45:52 +0800 Subject: [PATCH 005/117] chore: set tracing log to debug level --- frontend/appflowy_tauri/src-tauri/build.rs | 2 +- frontend/appflowy_tauri/src-tauri/src/init.rs | 31 ++++++++++--------- .../appflowy_tauri/src-tauri/tauri.conf.json | 5 ++- .../components/TestApiButton/TestGrid.tsx | 2 -- .../src/ts_event/event_template.tera | 2 +- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/frontend/appflowy_tauri/src-tauri/build.rs b/frontend/appflowy_tauri/src-tauri/build.rs index 795b9b7c83..d860e1e6a7 100644 --- a/frontend/appflowy_tauri/src-tauri/build.rs +++ b/frontend/appflowy_tauri/src-tauri/build.rs @@ -1,3 +1,3 @@ fn main() { - tauri_build::build() + tauri_build::build() } diff --git a/frontend/appflowy_tauri/src-tauri/src/init.rs b/frontend/appflowy_tauri/src-tauri/src/init.rs index f368fadb2f..a9d22eefbf 100644 --- a/frontend/appflowy_tauri/src-tauri/src/init.rs +++ b/frontend/appflowy_tauri/src-tauri/src/init.rs @@ -1,21 +1,22 @@ use flowy_core::{get_client_server_configuration, AppFlowyCore, AppFlowyCoreConfig}; pub fn init_flowy_core() -> AppFlowyCore { - let config_json = include_str!("../tauri.conf.json"); - let config: tauri_utils::config::Config = serde_json::from_str(config_json).unwrap(); + let config_json = include_str!("../tauri.conf.json"); + let config: tauri_utils::config::Config = serde_json::from_str(config_json).unwrap(); - let mut data_path = tauri::api::path::app_local_data_dir(&config).unwrap(); - if cfg!(debug_assertions) { - data_path.push("dev"); - } - data_path.push("data"); + let mut data_path = tauri::api::path::app_local_data_dir(&config).unwrap(); + if cfg!(debug_assertions) { + data_path.push("dev"); + } + data_path.push("data"); - let server_config = get_client_server_configuration().unwrap(); - let config = AppFlowyCoreConfig::new( - data_path.to_str().unwrap(), - "AppFlowy".to_string(), - server_config, - ) - .log_filter("trace", vec!["appflowy_tauri".to_string()]); - AppFlowyCore::new(config) + std::env::set_var("RUST_LOG", "debug"); + let server_config = get_client_server_configuration().unwrap(); + let config = AppFlowyCoreConfig::new( + data_path.to_str().unwrap(), + "AppFlowy".to_string(), + server_config, + ) + .log_filter("trace", vec!["appflowy_tauri".to_string()]); + AppFlowyCore::new(config) } diff --git a/frontend/appflowy_tauri/src-tauri/tauri.conf.json b/frontend/appflowy_tauri/src-tauri/tauri.conf.json index e2351d80a5..0a19ba6cc7 100644 --- a/frontend/appflowy_tauri/src-tauri/tauri.conf.json +++ b/frontend/appflowy_tauri/src-tauri/tauri.conf.json @@ -60,11 +60,10 @@ "windows": [ { "fullscreen": false, - "height": 1000, + "height": 1200, "resizable": true, "title": "AppFlowy", - "width": 1200, - "transparent": true + "width": 1200 } ] } diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx index b303d9a824..fb5584935b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx @@ -11,11 +11,9 @@ import { makeSingleSelectCellController, openTestDatabase, } from './DatabaseTestHelper'; -import assert from 'assert'; import { SelectOptionBackendService } from '../../stores/effects/database/cell/select_option_bd_svc'; import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller'; import { None, Some } from 'ts-results'; -import { TypeOptionBackendService } from '../../stores/effects/database/field/type_option/type_option_bd_svc'; import { RowBackendService } from '../../stores/effects/database/row/row_bd_svc'; export const TestCreateGrid = () => { diff --git a/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera b/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera index 13c02b4763..8444f304a8 100644 --- a/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera +++ b/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera @@ -27,7 +27,7 @@ export async function {{ event_func_name }}(): Promise Date: Wed, 1 Mar 2023 19:05:56 +0800 Subject: [PATCH 006/117] fix: filter notification with id --- .../components/TestApiButton/TestGrid.tsx | 3 ++- .../stores/effects/database/cell/cell_cache.ts | 1 - .../services/backend/notifications/observer.ts | 18 ++++++++++++------ 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx index fb5584935b..6882d19549 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx @@ -26,7 +26,7 @@ export const TestCreateGrid = () => { }, onRowsChanged: async (rows) => { if (rows.length !== 3) { - throw Error('Expected number of rows is 3, but receive ' + rows.length); + throw Error('Expected number of rows is 3, but receive ' + rows.length + view.id); } }, onFieldsChanged: (fields) => { @@ -36,6 +36,7 @@ export const TestCreateGrid = () => { }, }); await databaseController.open().then((result) => result.unwrap()); + await databaseController.dispose(); } return TestButton('Test create build-in grid', createBuildInGrid); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts index 979a06ee0b..27099145c3 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts @@ -15,7 +15,6 @@ export class CellCache { remove = (key: CellCacheKey) => { const cellDataByRowId = this.cellDataByFieldId.get(key.fieldId); if (cellDataByRowId !== undefined) { - console.log('cellDataByRowId', cellDataByRowId); cellDataByRowId.delete(key.rowId); } }; diff --git a/frontend/appflowy_tauri/src/services/backend/notifications/observer.ts b/frontend/appflowy_tauri/src/services/backend/notifications/observer.ts index 282886243c..c6f951288e 100644 --- a/frontend/appflowy_tauri/src/services/backend/notifications/observer.ts +++ b/frontend/appflowy_tauri/src/services/backend/notifications/observer.ts @@ -1,6 +1,6 @@ -import { listen, UnlistenFn } from '@tauri-apps/api/event'; -import { SubscribeObject } from '../models/flowy-notification'; -import { NotificationParser } from './parser'; +import { listen, UnlistenFn } from "@tauri-apps/api/event"; +import { SubscribeObject } from "../models/flowy-notification"; +import { NotificationParser } from "./parser"; export abstract class AFNotificationObserver { parser?: NotificationParser | null; @@ -11,9 +11,15 @@ export abstract class AFNotificationObserver { } async start() { - this._listener = await listen('af-notification', (notification) => { - const object = SubscribeObject.fromObject(notification.payload as {}); - this.parser?.parse(object); + this._listener = await listen("af-notification", (notification) => { + const object: SubscribeObject = SubscribeObject.fromObject(notification.payload as {}); + if (this.parser?.id !== undefined) { + if (object.id === this.parser.id) { + this.parser?.parse(object); + } + } else { + this.parser?.parse(object); + } }); } From 2e4df44c292c9aacac3ee95fb7f168567d0f0dd1 Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 1 Mar 2023 20:16:25 +0800 Subject: [PATCH 007/117] chore: add get single select type option data --- .../components/TestApiButton/TestAPI.tsx | 6 +- .../components/TestApiButton/TestGrid.tsx | 57 +++++++++++++++++-- .../database/cell/select_option_bd_svc.ts | 34 +++++++---- .../field/type_option/type_option_context.ts | 26 ++++++--- .../type_option/type_option_controller.ts | 6 +- 5 files changed, 101 insertions(+), 28 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx index a9ee26b174..0f9a1fb9d1 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx @@ -4,11 +4,12 @@ import { TestCreateGrid, TestCreateNewField, TestCreateRow, - TestCreateSelectOption, + TestCreateSelectOptionInCell, TestDeleteField, TestDeleteRow, TestEditCell, TestEditField, + TestGetSingleSelectFieldData, } from './TestGrid'; export const TestAPI = () => { @@ -20,7 +21,8 @@ export const TestAPI = () => { - + + diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx index 6882d19549..d0ccbfab47 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx @@ -1,5 +1,10 @@ import React from 'react'; -import { SelectOptionCellDataPB, ViewLayoutTypePB } from '../../../services/backend'; +import { + FieldType, + SelectOptionCellDataPB, + SingleSelectTypeOptionPB, + ViewLayoutTypePB, +} from '../../../services/backend'; import { Log } from '../../utils/log'; import { assertFieldName, @@ -11,10 +16,14 @@ import { makeSingleSelectCellController, openTestDatabase, } from './DatabaseTestHelper'; -import { SelectOptionBackendService } from '../../stores/effects/database/cell/select_option_bd_svc'; +import { + SelectOptionBackendService, + SelectOptionCellBackendService, +} from '../../stores/effects/database/cell/select_option_bd_svc'; import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller'; import { None, Some } from 'ts-results'; import { RowBackendService } from '../../stores/effects/database/row/row_bd_svc'; +import { makeSingleSelectTypeOptionContext } from '../../stores/effects/database/field/type_option/type_option_context'; export const TestCreateGrid = () => { async function createBuildInGrid() { @@ -95,8 +104,8 @@ export const TestDeleteRow = () => { return TestButton('Test delete row', testDeleteRow); }; -export const TestCreateSelectOption = () => { - async function testCreateOption() { +export const TestCreateSelectOptionInCell = () => { + async function testCreateOptionInCell() { const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); const databaseController = await openTestDatabase(view.id); await databaseController.open().then((result) => result.unwrap()); @@ -111,7 +120,7 @@ export const TestCreateSelectOption = () => { console.log(option); }, }); - const backendSvc = new SelectOptionBackendService(cellController.cellIdentifier); + const backendSvc = new SelectOptionCellBackendService(cellController.cellIdentifier); await backendSvc.createOption({ name: 'option' + index }); await cellController.dispose(); } @@ -119,7 +128,43 @@ export const TestCreateSelectOption = () => { await databaseController.dispose(); } - return TestButton('Test create a select option', testCreateOption); + return TestButton('Test create a select option in cell', testCreateOptionInCell); +}; + +export const TestGetSingleSelectFieldData = () => { + async function testGetSingleSelectFieldData() { + const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const databaseController = await openTestDatabase(view.id); + await databaseController.open().then((result) => result.unwrap()); + + // Find the single select column + const singleSelect = databaseController.fieldController.fieldInfos.find( + (fieldInfo) => fieldInfo.field.field_type === FieldType.SingleSelect + )!; + const typeOptionController = new TypeOptionController(view.id, Some(singleSelect)); + const singleSelectTypeOptionContext = makeSingleSelectTypeOptionContext(typeOptionController); + + // Create options + const singleSelectTypeOptionPB: SingleSelectTypeOptionPB = await singleSelectTypeOptionContext + .getTypeOption() + .then((result) => result.unwrap()); + const backendSvc = new SelectOptionBackendService(view.id, singleSelect.field.id); + const option1 = await backendSvc.createOption({ name: 'Task 1' }).then((result) => result.unwrap()); + singleSelectTypeOptionPB.options.splice(0, 0, option1); + const option2 = await backendSvc.createOption({ name: 'Task 2' }).then((result) => result.unwrap()); + singleSelectTypeOptionPB.options.splice(0, 0, option2); + const option3 = await backendSvc.createOption({ name: 'Task 3' }).then((result) => result.unwrap()); + singleSelectTypeOptionPB.options.splice(0, 0, option3); + await singleSelectTypeOptionContext.setTypeOption(singleSelectTypeOptionPB); + + // Read options + const options = singleSelectTypeOptionPB.options; + console.log(options); + + await databaseController.dispose(); + } + + return TestButton('Test get single-select column data', testGetSingleSelectFieldData); }; export const TestEditField = () => { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts index a70d5e1e7f..fb52dac1fd 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts @@ -14,6 +14,20 @@ import { } from '../../../../../services/backend/events/flowy-database'; export class SelectOptionBackendService { + constructor(public readonly viewId: string, public readonly fieldId: string) {} + + createOption = async (params: { name: string }) => { + const payload = CreateSelectOptionPayloadPB.fromObject({ + option_name: params.name, + view_id: this.viewId, + field_id: this.fieldId, + }); + + return DatabaseEventCreateSelectOption(payload); + }; +} + +export class SelectOptionCellBackendService { constructor(public readonly cellIdentifier: CellIdentifier) {} createOption = async (params: { name: string; isSelect?: boolean }) => { @@ -31,6 +45,16 @@ export class SelectOptionBackendService { } }; + private _insertOption = (option: SelectOptionPB, isSelect: boolean) => { + const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() }); + if (isSelect) { + payload.insert_options.push(option); + } else { + payload.update_options.push(option); + } + return DatabaseEventUpdateSelectOption(payload); + }; + updateOption = (option: SelectOptionPB) => { const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() }); payload.update_options.push(option); @@ -59,16 +83,6 @@ export class SelectOptionBackendService { return DatabaseEventUpdateSelectOptionCell(payload); }; - private _insertOption = (option: SelectOptionPB, isSelect: boolean) => { - const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() }); - if (isSelect) { - payload.insert_options.push(option); - } else { - payload.update_options.push(option); - } - return DatabaseEventUpdateSelectOption(payload); - }; - private _cellIdentifier = () => { return CellIdPB.fromObject({ view_id: this.cellIdentifier.viewId, diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts index d8ecebc328..8c7da56219 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts @@ -11,6 +11,7 @@ import { URLTypeOptionPB, } from '../../../../../../services/backend'; import { utf8Decoder, utf8Encoder } from '../../cell/data_parser'; +import { DatabaseFieldObserver } from '../field_observer'; abstract class TypeOptionSerde { abstract deserialize(buffer: Uint8Array): T; @@ -164,9 +165,17 @@ class ChecklistTypeOptionSerde extends TypeOptionSerde { export class TypeOptionContext { private typeOption: Option; + private fieldObserver: DatabaseFieldObserver; constructor(public readonly parser: TypeOptionSerde, private readonly controller: TypeOptionController) { this.typeOption = None; + this.fieldObserver = new DatabaseFieldObserver(controller.fieldId); + + void this.fieldObserver.subscribe({ + onFieldsChanged: () => { + void this.getTypeOption(); + }, + }); } get viewId(): string { @@ -174,20 +183,23 @@ export class TypeOptionContext { } getTypeOption = async (): Promise> => { - if (this.typeOption.some) { - return Ok(this.typeOption.val); - } - const result = await this.controller.getTypeOption(); if (result.ok) { - return Ok(this.parser.deserialize(result.val.type_option_data)); + const typeOption = this.parser.deserialize(result.val.type_option_data); + this.typeOption = Some(typeOption); + return Ok(typeOption); } else { return result; } }; - setTypeOption = (typeOption: T) => { - this.controller.typeOption = this.parser.serialize(typeOption); + // Save the typeOption to disk + setTypeOption = async (typeOption: T) => { + await this.controller.saveTypeOption(this.parser.serialize(typeOption)); this.typeOption = Some(typeOption); }; + + dispose = async () => { + await this.fieldObserver.unsubscribe(); + }; } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts index 3fc393a457..7993e119b9 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts @@ -59,10 +59,10 @@ export class TypeOptionController { } }; - set typeOption(data: Uint8Array) { + saveTypeOption = async (data: Uint8Array) => { if (this.typeOptionData.some) { this.typeOptionData.val.type_option_data = data; - void this.fieldBackendSvc?.updateTypeOption(data).then((result) => { + await this.fieldBackendSvc?.updateTypeOption(data).then((result) => { if (result.err) { Log.error(result.val); } @@ -70,7 +70,7 @@ export class TypeOptionController { } else { throw Error('Unexpect empty type option data. Should call initialize first'); } - } + }; deleteField = async () => { if (this.fieldBackendSvc === undefined) { From c35db5c2a232b0855b455739e6d87ae02fa7126d Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 2 Mar 2023 19:47:37 +0800 Subject: [PATCH 008/117] fix: high cpu usage --- frontend/appflowy_tauri/src-tauri/src/init.rs | 2 +- .../TestApiButton/DatabaseTestHelper.ts | 70 ++++++++--- .../components/TestApiButton/TestAPI.tsx | 4 + .../components/TestApiButton/TestGrid.tsx | 115 ++++++++++++++++-- .../effects/database/cell/cell_cache.ts | 17 +-- .../effects/database/cell/cell_controller.ts | 64 +++++----- .../effects/database/cell/cell_observer.ts | 25 ++-- .../database/cell/controller_builder.ts | 63 ++-------- .../effects/database/cell/data_parser.ts | 6 +- .../effects/database/cell/data_persistence.ts | 2 - .../database/cell/select_option_bd_svc.ts | 3 +- .../effects/database/database_controller.ts | 8 +- .../database/field/field_controller.ts | 49 ++++---- .../effects/database/field/field_observer.ts | 8 +- .../field/type_option/type_option_context.ts | 2 +- .../type_option/type_option_controller.ts | 24 +++- .../database/notifications/observer.ts | 4 +- .../stores/effects/database/row/row_cache.ts | 86 +++++++------ .../database/view/database_view_cache.ts | 3 +- .../database/view/view_row_observer.ts | 2 +- .../src/ts_event/event_template.tera | 1 + .../rust-lib/flowy-database/src/manager.rs | 46 ++++--- .../src/services/database/database_editor.rs | 4 +- .../src/services/database_view/editor.rs | 8 +- .../services/database_view/editor_manager.rs | 6 +- .../field/type_options/type_option_cell.rs | 1 + .../persistence/rev_sqlite/block_impl.rs | 33 +++-- .../persistence/rev_sqlite/database_impl.rs | 15 ++- .../persistence/rev_sqlite/view_impl.rs | 33 +++-- .../src/services/sort/controller.rs | 11 +- .../rev_sqlite/folder_rev_sqlite.rs | 15 ++- frontend/rust-lib/flowy-task/src/scheduler.rs | 49 +++----- 32 files changed, 454 insertions(+), 325 deletions(-) diff --git a/frontend/appflowy_tauri/src-tauri/src/init.rs b/frontend/appflowy_tauri/src-tauri/src/init.rs index a9d22eefbf..98ab6d5376 100644 --- a/frontend/appflowy_tauri/src-tauri/src/init.rs +++ b/frontend/appflowy_tauri/src-tauri/src/init.rs @@ -10,7 +10,7 @@ pub fn init_flowy_core() -> AppFlowyCore { } data_path.push("data"); - std::env::set_var("RUST_LOG", "debug"); + std::env::set_var("RUST_LOG", "trace"); let server_config = get_client_server_configuration().unwrap(); let config = AppFlowyCoreConfig::new( data_path.to_str().unwrap(), diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts index 4a79bc16e0..1eecc6f70a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/DatabaseTestHelper.ts @@ -11,7 +11,6 @@ import { SelectOptionCellController, TextCellController, } from '../../stores/effects/database/cell/controller_builder'; -import assert from 'assert'; import { None, Option, Some } from 'ts-results'; import { TypeOptionBackendService } from '../../stores/effects/database/field/type_option/type_option_bd_svc'; import { DatabaseBackendService } from '../../stores/effects/database/database_bd_svc'; @@ -29,9 +28,16 @@ export async function openTestDatabase(viewId: string): Promise result.unwrap()); - cellController.subscribeChanged({ +export async function assertTextCell( + fieldId: string, + rowInfo: RowInfo, + databaseController: DatabaseController, + expectedContent: string +) { + const cellController = await makeTextCellController(fieldId, rowInfo, databaseController).then((result) => + result.unwrap() + ); + await cellController.subscribeChanged({ onCellChanged: (value) => { const cellContent = value.unwrap(); if (cellContent !== expectedContent) { @@ -39,55 +45,78 @@ export async function assertTextCell(rowInfo: RowInfo, databaseController: Datab } }, }); - cellController.getCellData(); + await cellController.getCellData(); } -export async function editTextCell(rowInfo: RowInfo, databaseController: DatabaseController, content: string) { - const cellController = await makeTextCellController(rowInfo, databaseController).then((result) => result.unwrap()); +export async function editTextCell( + fieldId: string, + rowInfo: RowInfo, + databaseController: DatabaseController, + content: string +) { + const cellController = await makeTextCellController(fieldId, rowInfo, databaseController).then((result) => + result.unwrap() + ); await cellController.saveCellData(content); } export async function makeTextCellController( + fieldId: string, rowInfo: RowInfo, databaseController: DatabaseController ): Promise> { - const builder = await makeCellControllerBuilder(rowInfo, FieldType.RichText, databaseController).then((result) => - result.unwrap() + const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.RichText, databaseController).then( + (result) => result.unwrap() ); return Some(builder.build() as TextCellController); } export async function makeNumberCellController( + fieldId: string, rowInfo: RowInfo, databaseController: DatabaseController ): Promise> { - const builder = await makeCellControllerBuilder(rowInfo, FieldType.Number, databaseController).then((result) => - result.unwrap() + const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.Number, databaseController).then( + (result) => result.unwrap() ); return Some(builder.build() as NumberCellController); } export async function makeSingleSelectCellController( + fieldId: string, rowInfo: RowInfo, databaseController: DatabaseController ): Promise> { - const builder = await makeCellControllerBuilder(rowInfo, FieldType.SingleSelect, databaseController).then((result) => - result.unwrap() + const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.SingleSelect, databaseController).then( + (result) => result.unwrap() + ); + return Some(builder.build() as SelectOptionCellController); +} + +export async function makeMultiSelectCellController( + fieldId: string, + rowInfo: RowInfo, + databaseController: DatabaseController +): Promise> { + const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.MultiSelect, databaseController).then( + (result) => result.unwrap() ); return Some(builder.build() as SelectOptionCellController); } export async function makeDateCellController( + fieldId: string, rowInfo: RowInfo, databaseController: DatabaseController ): Promise> { - const builder = await makeCellControllerBuilder(rowInfo, FieldType.DateTime, databaseController).then((result) => - result.unwrap() + const builder = await makeCellControllerBuilder(fieldId, rowInfo, FieldType.DateTime, databaseController).then( + (result) => result.unwrap() ); return Some(builder.build() as DateCellController); } export async function makeCellControllerBuilder( + fieldId: string, rowInfo: RowInfo, fieldType: FieldType, databaseController: DatabaseController @@ -99,7 +128,7 @@ export async function makeCellControllerBuilder( const cellByFieldId = await rowController.loadCells(); for (const cellIdentifier of cellByFieldId.values()) { const builder = new CellControllerBuilder(cellIdentifier, cellCache, fieldController); - if (cellIdentifier.fieldType === fieldType) { + if (cellIdentifier.fieldId === fieldId) { return Some(builder); } } @@ -107,6 +136,15 @@ export async function makeCellControllerBuilder( return None; } +export function findFirstFieldInfoWithFieldType(rowInfo: RowInfo, fieldType: FieldType) { + const fieldInfo = rowInfo.fieldInfos.find((element) => element.field.field_type === fieldType); + if (fieldInfo === undefined) { + return None; + } else { + return Some(fieldInfo); + } +} + export async function assertFieldName(viewId: string, fieldId: string, fieldType: FieldType, expected: string) { const svc = new TypeOptionBackendService(viewId); const typeOptionPB = await svc.getTypeOption(fieldId, fieldType).then((result) => result.unwrap()); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx index 0f9a1fb9d1..b5354da161 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestAPI.tsx @@ -10,6 +10,8 @@ import { TestEditCell, TestEditField, TestGetSingleSelectFieldData, + TestSwitchFromMultiSelectToText, + TestSwitchFromSingleSelectToNumber, } from './TestGrid'; export const TestAPI = () => { @@ -26,6 +28,8 @@ export const TestAPI = () => { + +

); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx index d0ccbfab47..b4099252ce 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { FieldType, + NumberFormat, + NumberTypeOptionPB, SelectOptionCellDataPB, SingleSelectTypeOptionPB, ViewLayoutTypePB, @@ -13,7 +15,10 @@ import { assertTextCell, createTestDatabaseView, editTextCell, + findFirstFieldInfoWithFieldType, + makeMultiSelectCellController, makeSingleSelectCellController, + makeTextCellController, openTestDatabase, } from './DatabaseTestHelper'; import { @@ -23,7 +28,10 @@ import { import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller'; import { None, Some } from 'ts-results'; import { RowBackendService } from '../../stores/effects/database/row/row_bd_svc'; -import { makeSingleSelectTypeOptionContext } from '../../stores/effects/database/field/type_option/type_option_context'; +import { + makeNumberTypeOptionContext, + makeSingleSelectTypeOptionContext, +} from '../../stores/effects/database/field/type_option/type_option_context'; export const TestCreateGrid = () => { async function createBuildInGrid() { @@ -33,11 +41,11 @@ export const TestCreateGrid = () => { onViewChanged: (databasePB) => { Log.debug('Did receive database:' + databasePB); }, - onRowsChanged: async (rows) => { - if (rows.length !== 3) { - throw Error('Expected number of rows is 3, but receive ' + rows.length + view.id); - } - }, + // onRowsChanged: async (rows) => { + // if (rows.length !== 3) { + // throw Error('Expected number of rows is 3, but receive ' + rows.length); + // } + // }, onFieldsChanged: (fields) => { if (fields.length !== 3) { throw Error('Expected number of fields is 3, but receive ' + fields.length); @@ -59,8 +67,9 @@ export const TestEditCell = () => { for (const [index, row] of databaseController.databaseViewCache.rowInfos.entries()) { const cellContent = index.toString(); - await editTextCell(row, databaseController, cellContent); - await assertTextCell(row, databaseController, cellContent); + const fieldInfo = findFirstFieldInfoWithFieldType(row, FieldType.RichText).unwrap(); + await editTextCell(fieldInfo.field.id, row, databaseController, cellContent); + await assertTextCell(fieldInfo.field.id, row, databaseController, cellContent); } } @@ -111,10 +120,11 @@ export const TestCreateSelectOptionInCell = () => { await databaseController.open().then((result) => result.unwrap()); for (const [index, row] of databaseController.databaseViewCache.rowInfos.entries()) { if (index === 0) { - const cellController = await makeSingleSelectCellController(row, databaseController).then((result) => - result.unwrap() + const fieldInfo = findFirstFieldInfoWithFieldType(row, FieldType.SingleSelect).unwrap(); + const cellController = await makeSingleSelectCellController(fieldInfo.field.id, row, databaseController).then( + (result) => result.unwrap() ); - cellController.subscribeChanged({ + await cellController.subscribeChanged({ onCellChanged: (value) => { const option: SelectOptionCellDataPB = value.unwrap(); console.log(option); @@ -167,6 +177,89 @@ export const TestGetSingleSelectFieldData = () => { return TestButton('Test get single-select column data', testGetSingleSelectFieldData); }; +export const TestSwitchFromSingleSelectToNumber = () => { + async function testSwitchFromSingleSelectToNumber() { + const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const databaseController = await openTestDatabase(view.id); + await databaseController.open().then((result) => result.unwrap()); + + // Find the single select column + const singleSelect = databaseController.fieldController.fieldInfos.find( + (fieldInfo) => fieldInfo.field.field_type === FieldType.SingleSelect + )!; + const typeOptionController = new TypeOptionController(view.id, Some(singleSelect)); + await typeOptionController.switchToField(FieldType.Number); + + // Check the number type option + const numberTypeOptionContext = makeNumberTypeOptionContext(typeOptionController); + const numberTypeOption: NumberTypeOptionPB = await numberTypeOptionContext + .getTypeOption() + .then((result) => result.unwrap()); + const format: NumberFormat = numberTypeOption.format; + if (format !== NumberFormat.Num) { + throw Error('The default format should be number'); + } + + await databaseController.dispose(); + } + + return TestButton('Test switch from single-select to number column', testSwitchFromSingleSelectToNumber); +}; + +export const TestSwitchFromMultiSelectToText = () => { + async function testSwitchFromMultiSelectToRichText() { + const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); + const databaseController = await openTestDatabase(view.id); + await databaseController.open().then((result) => result.unwrap()); + + // Create multi-select field + const typeOptionController = new TypeOptionController(view.id, None, FieldType.MultiSelect); + await typeOptionController.initialize(); + + // Insert options to first row + const row = databaseController.databaseViewCache.rowInfos[0]; + const multiSelectField = typeOptionController.getFieldInfo(); + // const multiSelectField = findFirstFieldInfoWithFieldType(row, FieldType.MultiSelect).unwrap(); + const selectOptionCellController = await makeMultiSelectCellController( + multiSelectField.field.id, + row, + databaseController + ).then((result) => result.unwrap()); + const backendSvc = new SelectOptionCellBackendService(selectOptionCellController.cellIdentifier); + await backendSvc.createOption({ name: 'A' }); + await backendSvc.createOption({ name: 'B' }); + await backendSvc.createOption({ name: 'C' }); + + const selectOptionCellData = await selectOptionCellController.getCellData().then((result) => result.unwrap()); + if (selectOptionCellData.options.length !== 3) { + throw Error('The options should equal to 3'); + } + + if (selectOptionCellData.select_options.length !== 3) { + throw Error('The selected options should equal to 3'); + } + await selectOptionCellController.dispose(); + + // Switch to RichText field type + await typeOptionController.switchToField(FieldType.RichText).then((result) => result.unwrap()); + if (typeOptionController.fieldType !== FieldType.RichText) { + throw Error('The field type should be text'); + } + + const textCellController = await makeTextCellController(multiSelectField.field.id, row, databaseController).then( + (result) => result.unwrap() + ); + const cellContent = await textCellController.getCellData(); + if (cellContent.unwrap() !== 'A,B,C') { + throw Error('The cell content should be A,B,C, but receive: ' + cellContent.unwrap()); + } + + await databaseController.dispose(); + } + + return TestButton('Test switch from multi-select to text column', testSwitchFromMultiSelectToRichText); +}; + export const TestEditField = () => { async function testEditField() { const view = await createTestDatabaseView(ViewLayoutTypePB.Grid); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts index 27099145c3..a19ad13d27 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_cache.ts @@ -35,18 +35,19 @@ export class CellCache { }; get(key: CellCacheKey): Option { - const inner = this.cellDataByFieldId.get(key.fieldId); - if (inner === undefined) { + const cellDataByRowId = this.cellDataByFieldId.get(key.fieldId); + if (cellDataByRowId === undefined) { return None; } else { - const value = inner.get(key.rowId); - if (typeof value === typeof undefined || typeof value === typeof null) { + const value = cellDataByRowId.get(key.rowId); + if (typeof value === typeof undefined) { return None; } - if (value satisfies T) { - return Some(value as T); - } - return None; + + // if (value satisfies T) { + // return Some(value as T); + // } + return Some(value); } } } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts index c438cd6cc8..6d3050d88a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts @@ -8,28 +8,29 @@ import { ChangeNotifier } from '../../../../utils/change_notifier'; import { CellObserver } from './cell_observer'; import { Log } from '../../../../utils/log'; import { Err, None, Ok, Option, Some } from 'ts-results'; +import { DatabaseFieldObserver } from '../field/field_observer'; -export abstract class CellFieldNotifier { - abstract subscribeOnFieldChanged(callback: () => void): void; -} +type Callbacks = { onCellChanged: (value: Option) => void; onFieldChanged?: () => void }; export class CellController { private fieldBackendService: FieldBackendService; private cellDataNotifier: CellDataNotifier>; private cellObserver: CellObserver; private readonly cacheKey: CellCacheKey; + private readonly fieldNotifier: DatabaseFieldObserver; + private subscribeCallbacks?: Callbacks; constructor( public readonly cellIdentifier: CellIdentifier, private readonly cellCache: CellCache, - private readonly fieldNotifier: CellFieldNotifier, private readonly cellDataLoader: CellDataLoader, private readonly cellDataPersistence: CellDataPersistence ) { this.fieldBackendService = new FieldBackendService(cellIdentifier.viewId, cellIdentifier.fieldId); - this.cacheKey = new CellCacheKey(cellIdentifier.rowId, cellIdentifier.fieldId); + this.cacheKey = new CellCacheKey(cellIdentifier.fieldId, cellIdentifier.rowId); this.cellDataNotifier = new CellDataNotifier(cellCache.get(this.cacheKey)); this.cellObserver = new CellObserver(cellIdentifier.rowId, cellIdentifier.fieldId); + this.fieldNotifier = new DatabaseFieldObserver(cellIdentifier.fieldId); void this.cellObserver.subscribe({ /// 1.Listen on user edit event and load the new cell data if needed. /// For example: @@ -40,21 +41,23 @@ export class CellController { await this._loadCellData(); }, }); + + /// 2.Listen on the field event and load the cell data if needed. + void this.fieldNotifier.subscribe({ + onFieldChanged: () => { + this.subscribeCallbacks?.onFieldChanged?.(); + /// reloadOnFieldChanged should be true if you need to load the data when the corresponding field is changed + /// For example: + /// ¥12 -> $12 + if (this.cellDataLoader.reloadOnFieldChanged) { + void this._loadCellData(); + } + }, + }); } - subscribeChanged = (callbacks: { onCellChanged: (value: Option) => void; onFieldChanged?: () => void }) => { - /// 2.Listen on the field event and load the cell data if needed. - this.fieldNotifier.subscribeOnFieldChanged(async () => { - callbacks.onFieldChanged?.(); - - /// reloadOnFieldChanged should be true if you need to load the data when the corresponding field is changed - /// For example: - /// ¥12 -> $12 - if (this.cellDataLoader.reloadOnFieldChanged) { - await this._loadCellData(); - } - }); - + subscribeChanged = async (callbacks: Callbacks) => { + this.subscribeCallbacks = callbacks; this.cellDataNotifier.observer.subscribe((cellData) => { if (cellData !== null) { callbacks.onCellChanged(cellData); @@ -78,21 +81,21 @@ export class CellController { } }; - /// Return the cell data if it exists in the cache - /// If the cell data is not exist, it will load the cell - /// data from the backend and then the [onCellChanged] will - /// get called - getCellData = (): Option => { + /// Return the cell data immediately if it exists in the cache + /// Otherwise, it will load the cell data from the backend. The + /// subscribers of the [onCellChanged] will get noticed + getCellData = async (): Promise> => { const cellData = this.cellCache.get(this.cacheKey); if (cellData.none) { - void this._loadCellData(); + await this._loadCellData(); + return this.cellCache.get(this.cacheKey); } return cellData; }; private _loadCellData = () => { return this.cellDataLoader.loadData().then((result) => { - if (result.ok && result.val !== undefined) { + if (result.ok) { this.cellCache.insert(this.cacheKey, result.val); this.cellDataNotifier.cellData = Some(result.val); } else { @@ -104,19 +107,10 @@ export class CellController { dispose = async () => { await this.cellObserver.unsubscribe(); + await this.fieldNotifier.unsubscribe(); }; } -export class CellFieldNotifierImpl extends CellFieldNotifier { - constructor(private readonly fieldController: FieldController) { - super(); - } - - subscribeOnFieldChanged(callback: () => void): void { - this.fieldController.subscribeOnFieldsChanged(callback); - } -} - class CellDataNotifier extends ChangeNotifier { _cellData: T | null; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts index 06409c7ae2..9aa9763a99 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts @@ -8,24 +8,27 @@ type UpdateCellNotifiedValue = Result; export type CellChangedCallback = (value: UpdateCellNotifiedValue) => void; export class CellObserver { - private _notifier?: ChangeNotifier; - private _listener?: DatabaseNotificationObserver; + private notifier?: ChangeNotifier; + private listener?: DatabaseNotificationObserver; constructor(public readonly rowId: string, public readonly fieldId: string) {} subscribe = async (callbacks: { onCellChanged: CellChangedCallback }) => { - this._notifier = new ChangeNotifier(); - this._notifier?.observer.subscribe(callbacks.onCellChanged); + this.notifier = new ChangeNotifier(); + this.notifier?.observer.subscribe(callbacks.onCellChanged); - this._listener = new DatabaseNotificationObserver({ - viewId: this.rowId + ':' + this.fieldId, + this.listener = new DatabaseNotificationObserver({ + // The rowId combine with fieldId can identifier the cell. + // This format rowId:fieldId is also defined in the backend, + // so don't change this. + id: this.rowId + ':' + this.fieldId, parserHandler: (notification, result) => { switch (notification) { case DatabaseNotification.DidUpdateCell: if (result.ok) { - this._notifier?.notify(Ok.EMPTY); + this.notifier?.notify(Ok.EMPTY); } else { - this._notifier?.notify(result); + this.notifier?.notify(result); } return; default: @@ -33,11 +36,11 @@ export class CellObserver { } }, }); - await this._listener.start(); + await this.listener.start(); }; unsubscribe = async () => { - this._notifier?.unsubscribe(); - await this._listener?.stop(); + this.notifier?.unsubscribe(); + await this.listener?.stop(); }; } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts index 584e77394f..9d66dd6ee5 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts @@ -1,11 +1,6 @@ -import { - DateCellDataPB, - FieldType, - SelectOptionCellDataPB, - URLCellDataPB, -} from '../../../../../services/backend/models/flowy-database'; +import { DateCellDataPB, FieldType, SelectOptionCellDataPB, URLCellDataPB } from '../../../../../services/backend'; import { CellIdentifier } from './cell_bd_svc'; -import { CellController, CellFieldNotifierImpl } from './cell_controller'; +import { CellController } from './cell_controller'; import { CellDataLoader, DateCellDataParser, @@ -34,15 +29,11 @@ export class CalendarData { export type URLCellController = CellController; export class CellControllerBuilder { - _fieldNotifier: CellFieldNotifierImpl; - constructor( public readonly cellIdentifier: CellIdentifier, public readonly cellCache: CellCache, public readonly fieldController: FieldController - ) { - this._fieldNotifier = new CellFieldNotifierImpl(this.fieldController); - } + ) {} /// build = () => { @@ -68,77 +59,41 @@ export class CellControllerBuilder { const loader = new CellDataLoader(this.cellIdentifier, new SelectOptionCellDataParser(), true); const persistence = new TextCellDataPersistence(this.cellIdentifier); - return new CellController( - this.cellIdentifier, - this.cellCache, - this._fieldNotifier, - loader, - persistence - ); + return new CellController(this.cellIdentifier, this.cellCache, loader, persistence); }; makeURLCellController = (): URLCellController => { const loader = new CellDataLoader(this.cellIdentifier, new URLCellDataParser()); const persistence = new TextCellDataPersistence(this.cellIdentifier); - return new CellController( - this.cellIdentifier, - this.cellCache, - this._fieldNotifier, - loader, - persistence - ); + return new CellController(this.cellIdentifier, this.cellCache, loader, persistence); }; makeDateCellController = (): DateCellController => { const loader = new CellDataLoader(this.cellIdentifier, new DateCellDataParser(), true); const persistence = new DateCellDataPersistence(this.cellIdentifier); - return new CellController( - this.cellIdentifier, - this.cellCache, - this._fieldNotifier, - loader, - persistence - ); + return new CellController(this.cellIdentifier, this.cellCache, loader, persistence); }; makeNumberCellController = (): NumberCellController => { const loader = new CellDataLoader(this.cellIdentifier, new StringCellDataParser(), true); const persistence = new TextCellDataPersistence(this.cellIdentifier); - return new CellController( - this.cellIdentifier, - this.cellCache, - this._fieldNotifier, - loader, - persistence - ); + return new CellController(this.cellIdentifier, this.cellCache, loader, persistence); }; makeTextCellController = (): TextCellController => { const loader = new CellDataLoader(this.cellIdentifier, new StringCellDataParser()); const persistence = new TextCellDataPersistence(this.cellIdentifier); - return new CellController( - this.cellIdentifier, - this.cellCache, - this._fieldNotifier, - loader, - persistence - ); + return new CellController(this.cellIdentifier, this.cellCache, loader, persistence); }; makeCheckboxCellController = (): CheckboxCellController => { const loader = new CellDataLoader(this.cellIdentifier, new StringCellDataParser()); const persistence = new TextCellDataPersistence(this.cellIdentifier); - return new CellController( - this.cellIdentifier, - this.cellCache, - this._fieldNotifier, - loader, - persistence - ); + return new CellController(this.cellIdentifier, this.cellCache, loader, persistence); }; } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts index 0fdb978d72..e44867c0df 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts @@ -7,11 +7,11 @@ import { Err, Ok } from 'ts-results'; import { Log } from '../../../../utils/log'; abstract class CellDataParser { - abstract parserData(data: Uint8Array): T | undefined; + abstract parserData(data: Uint8Array): T; } class CellDataLoader { - _service = new CellBackendService(); + private service = new CellBackendService(); constructor( readonly cellId: CellIdentifier, @@ -20,7 +20,7 @@ class CellDataLoader { ) {} loadData = async () => { - const result = await this._service.getCell(this.cellId); + const result = await this.service.getCell(this.cellId); if (result.ok) { return Ok(this.parser.parserData(result.val.data)); } else { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts index 12845aaa64..26e0a4afb9 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts @@ -27,10 +27,8 @@ export class DateCellDataPersistence extends CellDataPersistence { save(data: CalendarData): Promise> { const payload = DateChangesetPB.fromObject({ cell_path: _makeCellPath(this.cellIdentifier) }); - payload.date = data.date.getUTCMilliseconds.toString(); payload.is_utc = true; - if (data.time !== undefined) { payload.time = data.time; } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts index fb52dac1fd..1ab1a61148 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts @@ -30,6 +30,7 @@ export class SelectOptionBackendService { export class SelectOptionCellBackendService { constructor(public readonly cellIdentifier: CellIdentifier) {} + // Creates a new option and insert this option to the cell createOption = async (params: { name: string; isSelect?: boolean }) => { const payload = CreateSelectOptionPayloadPB.fromObject({ option_name: params.name, @@ -39,7 +40,7 @@ export class SelectOptionCellBackendService { const result = await DatabaseEventCreateSelectOption(payload); if (result.ok) { - return this._insertOption(result.val, params.isSelect || true); + return await this._insertOption(result.val, params.isSelect || true); } else { return result; } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts index 25af4535ea..0ef8c27a1f 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts @@ -5,7 +5,7 @@ import { DatabasePB } from '../../../../services/backend/models/flowy-database/g import { RowChangedReason, RowInfo } from './row/row_cache'; import { Err, Ok } from 'ts-results'; -export type SubscribeCallback = { +export type SubscribeCallbacks = { onViewChanged?: (data: DatabasePB) => void; onRowsChanged?: (rowInfos: readonly RowInfo[], reason: RowChangedReason) => void; onFieldsChanged?: (fieldInfos: readonly FieldInfo[]) => void; @@ -15,7 +15,7 @@ export class DatabaseController { private backendService: DatabaseBackendService; fieldController: FieldController; databaseViewCache: DatabaseViewCache; - private _callback?: SubscribeCallback; + private _callback?: SubscribeCallbacks; constructor(public readonly viewId: string) { this.backendService = new DatabaseBackendService(viewId); @@ -23,9 +23,9 @@ export class DatabaseController { this.databaseViewCache = new DatabaseViewCache(viewId, this.fieldController); } - subscribe = (callbacks: SubscribeCallback) => { + subscribe = (callbacks: SubscribeCallbacks) => { this._callback = callbacks; - this.fieldController.subscribeOnFieldsChanged(callbacks.onFieldsChanged); + this.fieldController.subscribeOnNumOfFieldsChanged(callbacks.onFieldsChanged); this.databaseViewCache.getRowCache().subscribeOnRowsChanged((reason) => { this._callback?.onRowsChanged?.(this.databaseViewCache.rowInfos, reason); }); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts index 2d5a3959b2..05ab179325 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_controller.ts @@ -1,49 +1,49 @@ import { Log } from '../../../../utils/log'; import { DatabaseBackendService } from '../database_bd_svc'; import { DatabaseFieldChangesetObserver } from './field_observer'; -import { FieldIdPB, FieldPB, IndexFieldPB } from '../../../../../services/backend/models/flowy-database/field_entities'; +import { FieldIdPB, FieldPB, IndexFieldPB } from '../../../../../services/backend'; import { ChangeNotifier } from '../../../../utils/change_notifier'; export class FieldController { - private fieldListener: DatabaseFieldChangesetObserver; private backendService: DatabaseBackendService; - private fieldNotifier = new FieldNotifier([]); + private numOfFieldsObserver: DatabaseFieldChangesetObserver; + private numOfFieldsNotifier = new NumOfFieldsNotifier([]); constructor(public readonly viewId: string) { this.backendService = new DatabaseBackendService(viewId); - this.fieldListener = new DatabaseFieldChangesetObserver(viewId); + this.numOfFieldsObserver = new DatabaseFieldChangesetObserver(viewId); } dispose = async () => { - this.fieldNotifier.unsubscribe(); - await this.fieldListener.unsubscribe(); + this.numOfFieldsNotifier.unsubscribe(); + await this.numOfFieldsObserver.unsubscribe(); }; get fieldInfos(): readonly FieldInfo[] { - return this.fieldNotifier.fieldInfos; + return this.numOfFieldsNotifier.fieldInfos; } getField = (fieldId: string): FieldInfo | undefined => { - return this.fieldNotifier.fieldInfos.find((element) => element.field.id === fieldId); + return this.numOfFieldsNotifier.fieldInfos.find((element) => element.field.id === fieldId); }; loadFields = async (fieldIds: FieldIdPB[]) => { const result = await this.backendService.getFields(fieldIds); if (result.ok) { - this.fieldNotifier.fieldInfos = result.val.map((field) => new FieldInfo(field)); + this.numOfFieldsNotifier.fieldInfos = result.val.map((field) => new FieldInfo(field)); } else { Log.error(result.val); } }; - subscribeOnFieldsChanged = (callback?: (fieldInfos: readonly FieldInfo[]) => void) => { - return this.fieldNotifier.observer.subscribe((fieldInfos) => { + subscribeOnNumOfFieldsChanged = (callback?: (fieldInfos: readonly FieldInfo[]) => void) => { + return this.numOfFieldsNotifier.observer.subscribe((fieldInfos) => { callback?.(fieldInfos); }); }; listenOnFieldChanges = async () => { - await this.fieldListener.subscribe({ + await this.numOfFieldsObserver.subscribe({ onFieldsChanged: (result) => { if (result.ok) { const changeset = result.val; @@ -57,7 +57,7 @@ export class FieldController { }); }; - _deleteFields = (deletedFields: FieldIdPB[]) => { + private _deleteFields = (deletedFields: FieldIdPB[]) => { if (deletedFields.length === 0) { return; } @@ -68,10 +68,10 @@ export class FieldController { }; const newFieldInfos = [...this.fieldInfos]; newFieldInfos.filter(predicate); - this.fieldNotifier.fieldInfos = newFieldInfos; + this.numOfFieldsNotifier.fieldInfos = newFieldInfos; }; - _insertFields = (insertedFields: IndexFieldPB[]) => { + private _insertFields = (insertedFields: IndexFieldPB[]) => { if (insertedFields.length === 0) { return; } @@ -84,29 +84,28 @@ export class FieldController { newFieldInfos.push(fieldInfo); } }); - this.fieldNotifier.fieldInfos = newFieldInfos; + this.numOfFieldsNotifier.fieldInfos = newFieldInfos; }; - _updateFields = (updatedFields: FieldPB[]) => { + private _updateFields = (updatedFields: FieldPB[]) => { if (updatedFields.length === 0) { return; } const newFieldInfos = [...this.fieldInfos]; updatedFields.forEach((updatedField) => { - newFieldInfos.map((element) => { - if (element.field.id === updatedField.id) { - return updatedField; - } else { - return element; - } + const index = newFieldInfos.findIndex((fieldInfo) => { + return fieldInfo.field.id === updatedField.id; }); + if (index !== -1) { + newFieldInfos.splice(index, 1, new FieldInfo(updatedField)); + } }); - this.fieldNotifier.fieldInfos = newFieldInfos; + this.numOfFieldsNotifier.fieldInfos = newFieldInfos; }; } -class FieldNotifier extends ChangeNotifier { +class NumOfFieldsNotifier extends ChangeNotifier { constructor(private _fieldInfos: FieldInfo[]) { super(); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts index 423faac3db..9d7daec7df 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/field_observer.ts @@ -17,7 +17,7 @@ export class DatabaseFieldChangesetObserver { this.notifier?.observer.subscribe(callbacks.onFieldsChanged); this.listener = new DatabaseNotificationObserver({ - viewId: this.viewId, + id: this.viewId, parserHandler: (notification, result) => { switch (notification) { case DatabaseNotification.DidUpdateFields: @@ -50,12 +50,12 @@ export class DatabaseFieldObserver { constructor(public readonly fieldId: string) {} - subscribe = async (callbacks: { onFieldsChanged: FieldNotificationCallback }) => { + subscribe = async (callbacks: { onFieldChanged: FieldNotificationCallback }) => { this._notifier = new ChangeNotifier(); - this._notifier?.observer.subscribe(callbacks.onFieldsChanged); + this._notifier?.observer.subscribe(callbacks.onFieldChanged); this._listener = new DatabaseNotificationObserver({ - viewId: this.fieldId, + id: this.fieldId, parserHandler: (notification, result) => { switch (notification) { case DatabaseNotification.DidUpdateField: diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts index 8c7da56219..3fc184cf20 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_context.ts @@ -172,7 +172,7 @@ export class TypeOptionContext { this.fieldObserver = new DatabaseFieldObserver(controller.fieldId); void this.fieldObserver.subscribe({ - onFieldsChanged: () => { + onFieldChanged: () => { void this.getTypeOption(); }, }); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts index 7993e119b9..1961cae413 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/field/type_option/type_option_controller.ts @@ -13,14 +13,20 @@ export class TypeOptionController { private typeOptionBackendSvc: TypeOptionBackendService; // Must call [initialize] if the passed-in fieldInfo is None - constructor(public readonly viewId: string, private initialFieldInfo: Option = None) { + constructor( + public readonly viewId: string, + private readonly initialFieldInfo: Option = None, + private readonly defaultFieldType: FieldType = FieldType.RichText + ) { this.typeOptionData = None; this.typeOptionBackendSvc = new TypeOptionBackendService(viewId); } + // It will create a new field for the defaultFieldType if the [initialFieldInfo] is None. + // Otherwise, it will get the type option of the [initialFieldInfo] initialize = async () => { if (this.initialFieldInfo.none) { - await this.createTypeOption(); + await this.createTypeOption(this.defaultFieldType); } else { await this.getTypeOption(); } @@ -45,8 +51,16 @@ export class TypeOptionController { return new FieldInfo(this.typeOptionData.val.field); }; - switchToField = (fieldType: FieldType) => { - return this.typeOptionBackendSvc.updateTypeOptionType(this.fieldId, fieldType); + switchToField = async (fieldType: FieldType) => { + const result = await this.typeOptionBackendSvc.updateTypeOptionType(this.fieldId, fieldType); + if (result.ok) { + const getResult = await this.typeOptionBackendSvc.getTypeOption(this.fieldId, fieldType); + if (getResult.ok) { + this.updateTypeOptionData(getResult.val); + } + return getResult; + } + return result; }; setFieldName = async (name: string) => { @@ -96,7 +110,7 @@ export class TypeOptionController { }); }; - private createTypeOption = (fieldType: FieldType = FieldType.RichText) => { + private createTypeOption = (fieldType: FieldType) => { return this.typeOptionBackendSvc.createTypeOption(fieldType).then((result) => { if (result.ok) { this.updateTypeOptionData(result.val); diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts index 186e3276b0..aca10af257 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/notifications/observer.ts @@ -6,10 +6,10 @@ import { Result } from 'ts-results'; export type ParserHandler = (notification: DatabaseNotification, result: Result) => void; export class DatabaseNotificationObserver extends AFNotificationObserver { - constructor(params: { viewId?: string; parserHandler: ParserHandler }) { + constructor(params: { id?: string; parserHandler: ParserHandler }) { const parser = new DatabaseNotificationParser({ callback: params.parserHandler, - id: params.viewId, + id: params.id, }); super(parser); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_cache.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_cache.ts index a9d7499f19..2d68d161a4 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_cache.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/row/row_cache.ts @@ -19,26 +19,26 @@ import { Log } from '../../../../utils/log'; export type CellByFieldId = Map; export class RowCache { - private readonly _rowList: RowList; - private readonly _cellCache: CellCache; - private readonly _notifier: RowChangeNotifier; + private readonly rowList: RowList; + private readonly cellCache: CellCache; + private readonly notifier: RowChangeNotifier; constructor(public readonly viewId: string, private readonly getFieldInfos: () => readonly FieldInfo[]) { - this._rowList = new RowList(); - this._cellCache = new CellCache(viewId); - this._notifier = new RowChangeNotifier(); + this.rowList = new RowList(); + this.cellCache = new CellCache(viewId); + this.notifier = new RowChangeNotifier(); } get rows(): readonly RowInfo[] { - return this._rowList.rows; + return this.rowList.rows; } getCellCache = () => { - return this._cellCache; + return this.cellCache; }; loadCells = async (rowId: string): Promise => { - const opRow = this._rowList.getRow(rowId); + const opRow = this.rowList.getRow(rowId); if (opRow.some) { return this._toCellMap(opRow.val.row.id, this.getFieldInfos()); } else { @@ -54,7 +54,7 @@ export class RowCache { }; subscribeOnRowsChanged = (callback: (reason: RowChangedReason, cellMap?: Map) => void) => { - return this._notifier.observer.subscribe((change) => { + return this.notifier.observer.subscribe((change) => { if (change.rowId !== undefined) { callback(change.reason, this._toCellMap(change.rowId, this.getFieldInfos())); } else { @@ -65,18 +65,19 @@ export class RowCache { onFieldUpdated = (fieldInfo: FieldInfo) => { // Remove the cell data if the corresponding field was changed - this._cellCache.removeWithFieldId(fieldInfo.field.id); + this.cellCache.removeWithFieldId(fieldInfo.field.id); }; - onNumberOfFieldsUpdated = () => { - this._notifier.withChange(RowChangedReason.FieldDidChanged); + onNumberOfFieldsUpdated = (fieldInfos: readonly FieldInfo[]) => { + this.rowList.setFieldInfos(fieldInfos); + this.notifier.withChange(RowChangedReason.FieldDidChanged); }; initializeRows = (rows: RowPB[]) => { rows.forEach((rowPB) => { - this._rowList.push(this._toRowInfo(rowPB)); + this.rowList.push(this._toRowInfo(rowPB)); }); - this._notifier.withChange(RowChangedReason.ReorderRows); + this.notifier.withChange(RowChangedReason.ReorderRows); }; applyRowsChanged = (changeset: RowsChangesetPB) => { @@ -91,15 +92,15 @@ export class RowCache { }; applyReorderRows = (rowIds: string[]) => { - this._rowList.reorderByRowIds(rowIds); - this._notifier.withChange(RowChangedReason.ReorderRows); + this.rowList.reorderByRowIds(rowIds); + this.notifier.withChange(RowChangedReason.ReorderRows); }; applyReorderSingleRow = (reorderRow: ReorderSingleRowPB) => { - const rowInfo = this._rowList.getRow(reorderRow.row_id); + const rowInfo = this.rowList.getRow(reorderRow.row_id); if (rowInfo !== undefined) { - this._rowList.move({ rowId: reorderRow.row_id, fromIndex: reorderRow.old_index, toIndex: reorderRow.new_index }); - this._notifier.withChange(RowChangedReason.ReorderSingleRow, reorderRow.row_id); + this.rowList.move({ rowId: reorderRow.row_id, fromIndex: reorderRow.old_index, toIndex: reorderRow.new_index }); + this.notifier.withChange(RowChangedReason.ReorderSingleRow, reorderRow.row_id); } }; @@ -108,14 +109,14 @@ export class RowCache { return; } const updatedRow = opRow.row; - const option = this._rowList.getRowWithIndex(updatedRow.id); + const option = this.rowList.getRowWithIndex(updatedRow.id); if (option.some) { const { rowInfo, index } = option.val; - this._rowList.remove(rowInfo.row.id); - this._rowList.insert(index, rowInfo.copyWith({ row: updatedRow })); + this.rowList.remove(rowInfo.row.id); + this.rowList.insert(index, rowInfo.copyWith({ row: updatedRow })); } else { const newRowInfo = new RowInfo(this.viewId, this.getFieldInfos(), updatedRow); - this._rowList.push(newRowInfo); + this.rowList.push(newRowInfo); } }; @@ -126,9 +127,9 @@ export class RowCache { private _deleteRows = (rowIds: string[]) => { rowIds.forEach((rowId) => { - const deletedRow = this._rowList.remove(rowId); + const deletedRow = this.rowList.remove(rowId); if (deletedRow !== undefined) { - this._notifier.withChange(RowChangedReason.Delete, deletedRow.rowInfo.row.id); + this.notifier.withChange(RowChangedReason.Delete, deletedRow.rowInfo.row.id); } }); }; @@ -136,9 +137,9 @@ export class RowCache { private _insertRows = (rows: InsertedRowPB[]) => { rows.forEach((insertedRow) => { const rowInfo = this._toRowInfo(insertedRow.row); - const insertedIndex = this._rowList.insert(insertedRow.index, rowInfo); + const insertedIndex = this.rowList.insert(insertedRow.index, rowInfo); if (insertedIndex !== undefined) { - this._notifier.withChange(RowChangedReason.Insert, insertedIndex.rowId); + this.notifier.withChange(RowChangedReason.Insert, insertedIndex.rowId); } }); }; @@ -152,39 +153,39 @@ export class RowCache { updatedRows.forEach((updatedRow) => { updatedRow.field_ids.forEach((fieldId) => { const key = new CellCacheKey(fieldId, updatedRow.row.id); - this._cellCache.remove(key); + this.cellCache.remove(key); }); rowInfos.push(this._toRowInfo(updatedRow.row)); }); - const updatedIndexs = this._rowList.insertRows(rowInfos); + const updatedIndexs = this.rowList.insertRows(rowInfos); updatedIndexs.forEach((row) => { - this._notifier.withChange(RowChangedReason.Update, row.rowId); + this.notifier.withChange(RowChangedReason.Update, row.rowId); }); }; private _hideRows = (rowIds: string[]) => { rowIds.forEach((rowId) => { - const deletedRow = this._rowList.remove(rowId); + const deletedRow = this.rowList.remove(rowId); if (deletedRow !== undefined) { - this._notifier.withChange(RowChangedReason.Delete, deletedRow.rowInfo.row.id); + this.notifier.withChange(RowChangedReason.Delete, deletedRow.rowInfo.row.id); } }); }; private _displayRows = (insertedRows: InsertedRowPB[]) => { insertedRows.forEach((insertedRow) => { - const insertedIndex = this._rowList.insert(insertedRow.index, this._toRowInfo(insertedRow.row)); + const insertedIndex = this.rowList.insert(insertedRow.index, this._toRowInfo(insertedRow.row)); if (insertedIndex !== undefined) { - this._notifier.withChange(RowChangedReason.Insert, insertedIndex.rowId); + this.notifier.withChange(RowChangedReason.Insert, insertedIndex.rowId); } }); }; dispose = async () => { - this._notifier.dispose(); + this.notifier.dispose(); }; private _toRowInfo = (rowPB: RowPB) => { @@ -219,7 +220,6 @@ class RowList { return Some(rowInfo); } }; - getRowWithIndex = (rowId: string): Option<{ rowInfo: RowInfo; index: number }> => { const rowInfo = this._rowInfoByRowId.get(rowId); if (rowInfo !== undefined) { @@ -322,6 +322,14 @@ class RowList { includes = (rowId: string): boolean => { return this._rowInfoByRowId.has(rowId); }; + + setFieldInfos = (fieldInfos: readonly FieldInfo[]) => { + const newRowInfos: RowInfo[] = []; + this._rowInfos.forEach((rowInfo) => { + newRowInfos.push(rowInfo.copyWith({ fieldInfos: fieldInfos })); + }); + this._rowInfos = newRowInfos; + }; } export class RowInfo { @@ -331,8 +339,8 @@ export class RowInfo { public readonly row: RowPB ) {} - copyWith = (params: { row?: RowPB }) => { - return new RowInfo(this.viewId, this.fieldInfos, params.row || this.row); + copyWith = (params: { row?: RowPB; fieldInfos?: readonly FieldInfo[] }) => { + return new RowInfo(this.viewId, params.fieldInfos || this.fieldInfos, params.row || this.row); }; } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts index 29b783864a..2a5d9303e6 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/database_view_cache.ts @@ -12,10 +12,11 @@ export class DatabaseViewCache { constructor(public readonly viewId: string, fieldController: FieldController) { this.rowsObserver = new DatabaseViewRowsObserver(viewId); this.rowCache = new RowCache(viewId, () => fieldController.fieldInfos); - this.fieldSubscription = fieldController.subscribeOnFieldsChanged((fieldInfos) => { + this.fieldSubscription = fieldController.subscribeOnNumOfFieldsChanged((fieldInfos) => { fieldInfos.forEach((fieldInfo) => { this.rowCache.onFieldUpdated(fieldInfo); }); + this.rowCache.onNumberOfFieldsUpdated(fieldInfos); }); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts index 1bc3f4de6e..198c86e598 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts @@ -38,7 +38,7 @@ export class DatabaseViewRowsObserver { this.reorderSingleRowNotifier.observer.subscribe(callbacks.onReorderSingleRow); this._listener = new DatabaseNotificationObserver({ - viewId: this.viewId, + id: this.viewId, parserHandler: (notification, result) => { switch (notification) { case DatabaseNotification.DidUpdateViewRowsVisibility: diff --git a/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera b/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera index 8444f304a8..2b23f78768 100644 --- a/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera +++ b/frontend/rust-lib/flowy-codegen/src/ts_event/event_template.tera @@ -27,6 +27,7 @@ export async function {{ event_func_name }}(): Promise Result; @@ -118,7 +118,6 @@ impl DatabaseManager { Ok(()) } - #[tracing::instrument(level = "debug", skip_all, err)] pub async fn create_database_block>( &self, block_id: T, @@ -141,33 +140,32 @@ impl DatabaseManager { .await } + #[tracing::instrument(level = "debug", skip_all)] pub async fn close_database_view>(&self, view_id: T) -> FlowyResult<()> { let view_id = view_id.as_ref(); let database_info = self.database_ref_indexer.get_database_with_view(view_id)?; tracing::Span::current().record("database_id", &database_info.database_id); - let mut should_remove_editor = false; - if let Some(database_editor) = self - .editors_by_database_id - .write() - .await - .get(&database_info.database_id) - { - database_editor.close_view_editor(view_id).await; - should_remove_editor = database_editor.number_of_ref_views().await == 0; - if should_remove_editor { - database_editor.dispose().await; - } + match self.editors_by_database_id.try_write() { + Ok(mut write_guard) => { + if let Some(database_editor) = write_guard.remove(&database_info.database_id) { + database_editor.close_view_editor(view_id).await; + if database_editor.number_of_ref_views().await == 0 { + database_editor.dispose().await; + } else { + self + .editors_by_database_id + .write() + .await + .insert(database_info.database_id, database_editor); + } + } + }, + Err(_) => { + tracing::error!("Try to get the lock of editors_by_database_id failed"); + }, } - if should_remove_editor { - tracing::debug!("Close database base editor: {}", database_info.database_id); - self - .editors_by_database_id - .write() - .await - .remove(&database_info.database_id); - } Ok(()) } @@ -235,12 +233,10 @@ impl DatabaseManager { pool: Arc, ) -> Result, FlowyError> { let user = self.database_user.clone(); - tracing::debug!("Open database view: {}", view_id); let (base_view_pad, base_view_rev_manager) = make_database_view_revision_pad(view_id, user.clone()).await?; let mut database_id = base_view_pad.database_id.clone(); - - tracing::debug!("Open database: {}", database_id); + tracing::debug!("Open database: {} with view: {}", database_id, view_id); if database_id.is_empty() { // Before the database_id concept comes up, we used the view_id directly. So if // the database_id is empty, which means we can used the view_id. After the version 0.1.1, diff --git a/frontend/rust-lib/flowy-database/src/services/database/database_editor.rs b/frontend/rust-lib/flowy-database/src/services/database/database_editor.rs index f497051afb..701ff72a98 100644 --- a/frontend/rust-lib/flowy-database/src/services/database/database_editor.rs +++ b/frontend/rust-lib/flowy-database/src/services/database/database_editor.rs @@ -116,13 +116,13 @@ impl DatabaseEditor { self.database_views.open(view_editor).await } - #[tracing::instrument(name = "Close database editor view", level = "debug", skip_all)] + #[tracing::instrument(level = "debug", skip_all)] pub async fn close_view_editor(&self, view_id: &str) { - self.rev_manager.generate_snapshot().await; self.database_views.close(view_id).await; } pub async fn dispose(&self) { + self.rev_manager.generate_snapshot().await; self.database_blocks.close().await; self.rev_manager.close().await; } diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs b/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs index 3454290ce4..e6918b9f50 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs @@ -178,12 +178,12 @@ impl DatabaseViewEditor { .await } - #[tracing::instrument(name = "close grid view editor", level = "trace", skip_all)] + #[tracing::instrument(name = "close database view editor", level = "trace", skip_all)] pub async fn close(&self) { self.rev_manager.generate_snapshot().await; self.rev_manager.close().await; self.filter_controller.close().await; - self.sort_controller.read().await.close().await; + self.sort_controller.write().await.close().await; } pub async fn handle_block_event(&self, event: Cow<'_, DatabaseBlockEvent>) { @@ -509,8 +509,8 @@ impl DatabaseViewEditor { .did_receive_changes(SortChangeset::from_insert(sort_type)) .await }; - self.notify_did_update_sort(changeset).await; drop(sort_controller); + self.notify_did_update_sort(changeset).await; Ok(sort_rev) } @@ -539,7 +539,7 @@ impl DatabaseViewEditor { pub async fn v_delete_all_sorts(&self) -> FlowyResult<()> { let all_sorts = self.v_get_all_sorts().await; - self.sort_controller.write().await.delete_all_sorts().await; + // self.sort_controller.write().await.delete_all_sorts().await; self .modify(|pad| { let changeset = pad.delete_all_sorts()?; diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs index 854d94f676..05975b1fb2 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs @@ -60,7 +60,11 @@ impl DatabaseViews { } pub async fn close(&self, view_id: &str) { - self.view_editors.write().await.remove(view_id).await; + if let Ok(mut view_editors) = self.view_editors.try_write() { + view_editors.remove(view_id).await; + } else { + tracing::error!("Try to get the lock of view_editors failed"); + } } pub async fn number_of_views(&self) -> usize { diff --git a/frontend/rust-lib/flowy-database/src/services/field/type_options/type_option_cell.rs b/frontend/rust-lib/flowy-database/src/services/field/type_options/type_option_cell.rs index 36e5f99466..b3f1e8e8cd 100644 --- a/frontend/rust-lib/flowy-database/src/services/field/type_options/type_option_cell.rs +++ b/frontend/rust-lib/flowy-database/src/services/field/type_options/type_option_cell.rs @@ -289,6 +289,7 @@ where decoded_field_type: &FieldType, field_rev: &FieldRevision, ) -> FlowyResult { + // tracing::debug!("get_cell_data: {:?}", std::any::type_name::()); let cell_data = if self.transformable() { match self.transform_type_option_cell_str(&cell_str, decoded_field_type, field_rev) { None => self.get_decoded_cell_data(cell_str, decoded_field_type, field_rev)?, diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/block_impl.rs b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/block_impl.rs index bfd640bba1..fadaec2ff9 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/block_impl.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/block_impl.rs @@ -22,7 +22,7 @@ impl RevisionDiskCache> for SQLiteDatabaseBlockRevisionPersi fn create_revision_records(&self, revision_records: Vec) -> Result<(), Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - GridMetaRevisionSql::create(revision_records, &conn)?; + DatabaseBlockMetaRevisionSql::create(revision_records, &conn)?; Ok(()) } @@ -36,7 +36,7 @@ impl RevisionDiskCache> for SQLiteDatabaseBlockRevisionPersi rev_ids: Option>, ) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let records = GridMetaRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; + let records = DatabaseBlockMetaRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; Ok(records) } @@ -47,7 +47,7 @@ impl RevisionDiskCache> for SQLiteDatabaseBlockRevisionPersi ) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; let revisions = - GridMetaRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; + DatabaseBlockMetaRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; Ok(revisions) } @@ -55,7 +55,7 @@ impl RevisionDiskCache> for SQLiteDatabaseBlockRevisionPersi let conn = &*self.pool.get().map_err(internal_error)?; conn.immediate_transaction::<_, FlowyError, _>(|| { for changeset in changesets { - GridMetaRevisionSql::update(changeset, conn)?; + DatabaseBlockMetaRevisionSql::update(changeset, conn)?; } Ok(()) })?; @@ -68,7 +68,7 @@ impl RevisionDiskCache> for SQLiteDatabaseBlockRevisionPersi rev_ids: Option>, ) -> Result<(), Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; - GridMetaRevisionSql::delete(object_id, rev_ids, conn)?; + DatabaseBlockMetaRevisionSql::delete(object_id, rev_ids, conn)?; Ok(()) } @@ -80,8 +80,8 @@ impl RevisionDiskCache> for SQLiteDatabaseBlockRevisionPersi ) -> Result<(), Self::Error> { let conn = self.pool.get().map_err(internal_error)?; conn.immediate_transaction::<_, FlowyError, _>(|| { - GridMetaRevisionSql::delete(object_id, deleted_rev_ids, &conn)?; - GridMetaRevisionSql::create(inserted_records, &conn)?; + DatabaseBlockMetaRevisionSql::delete(object_id, deleted_rev_ids, &conn)?; + DatabaseBlockMetaRevisionSql::create(inserted_records, &conn)?; Ok(()) }) } @@ -96,8 +96,8 @@ impl SQLiteDatabaseBlockRevisionPersistence { } } -struct GridMetaRevisionSql(); -impl GridMetaRevisionSql { +struct DatabaseBlockMetaRevisionSql(); +impl DatabaseBlockMetaRevisionSql { fn create(revision_records: Vec, conn: &SqliteConnection) -> Result<(), FlowyError> { // Batch insert: https://diesel.rs/guides/all-about-inserts.html @@ -105,7 +105,8 @@ impl GridMetaRevisionSql { .into_iter() .map(|record| { tracing::trace!( - "[GridMetaRevisionSql] create revision: {}:{:?}", + "[{}] create revision: {}:{:?}", + std::any::type_name::(), record.revision.object_id, record.revision.rev_id ); @@ -133,7 +134,8 @@ impl GridMetaRevisionSql { .filter(dsl::object_id.eq(changeset.object_id)); let _ = update(filter).set(dsl::state.eq(state)).execute(conn)?; tracing::debug!( - "[GridMetaRevisionSql] update revision:{} state:to {:?}", + "[{}] update revision:{} state:to {:?}", + std::any::type_name::(), changeset.rev_id, changeset.state ); @@ -193,7 +195,8 @@ impl GridMetaRevisionSql { if let Some(rev_ids) = rev_ids { tracing::trace!( - "[GridMetaRevisionSql] Delete revision: {}:{:?}", + "[{}] Delete revision: {}:{:?}", + std::any::type_name::(), object_id, rev_ids ); @@ -201,7 +204,11 @@ impl GridMetaRevisionSql { } let affected_row = sql.execute(conn)?; - tracing::trace!("[GridMetaRevisionSql] Delete {} rows", affected_row); + tracing::trace!( + "[{}] Delete {} rows", + std::any::type_name::(), + affected_row + ); Ok(()) } } diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/database_impl.rs b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/database_impl.rs index d146a01116..7a84e02f32 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/database_impl.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/database_impl.rs @@ -104,7 +104,8 @@ impl DatabaseRevisionSql { .into_iter() .map(|record| { tracing::trace!( - "[GridRevisionSql] create revision: {}:{:?}", + "[{}] create revision: {}:{:?}", + std::any::type_name::(), record.revision.object_id, record.revision.rev_id ); @@ -132,7 +133,8 @@ impl DatabaseRevisionSql { .filter(dsl::object_id.eq(changeset.object_id)); let _ = update(filter).set(dsl::state.eq(state)).execute(conn)?; tracing::debug!( - "[GridRevisionSql] update revision:{} state:to {:?}", + "[{}] update revision:{} state:to {:?}", + std::any::type_name::(), changeset.rev_id, changeset.state ); @@ -192,7 +194,8 @@ impl DatabaseRevisionSql { if let Some(rev_ids) = rev_ids { tracing::trace!( - "[GridRevisionSql] Delete revision: {}:{:?}", + "[{}] Delete revision: {}:{:?}", + std::any::type_name::(), object_id, rev_ids ); @@ -200,7 +203,11 @@ impl DatabaseRevisionSql { } let affected_row = sql.execute(conn)?; - tracing::trace!("[GridRevisionSql] Delete {} rows", affected_row); + tracing::trace!( + "[{}] Delete {} rows", + std::any::type_name::(), + affected_row + ); Ok(()) } } diff --git a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/view_impl.rs b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/view_impl.rs index df076b62e7..d6f4340f7e 100644 --- a/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/view_impl.rs +++ b/frontend/rust-lib/flowy-database/src/services/persistence/rev_sqlite/view_impl.rs @@ -31,7 +31,7 @@ impl RevisionDiskCache> for SQLiteDatabaseViewRevisionPersis fn create_revision_records(&self, revision_records: Vec) -> Result<(), Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - GridViewRevisionSql::create(revision_records, &conn)?; + DatabaseViewRevisionSql::create(revision_records, &conn)?; Ok(()) } @@ -45,7 +45,7 @@ impl RevisionDiskCache> for SQLiteDatabaseViewRevisionPersis rev_ids: Option>, ) -> Result, Self::Error> { let conn = self.pool.get().map_err(internal_error)?; - let records = GridViewRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; + let records = DatabaseViewRevisionSql::read(&self.user_id, object_id, rev_ids, &conn)?; Ok(records) } @@ -56,7 +56,7 @@ impl RevisionDiskCache> for SQLiteDatabaseViewRevisionPersis ) -> Result, Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; let revisions = - GridViewRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; + DatabaseViewRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?; Ok(revisions) } @@ -64,7 +64,7 @@ impl RevisionDiskCache> for SQLiteDatabaseViewRevisionPersis let conn = &*self.pool.get().map_err(internal_error)?; conn.immediate_transaction::<_, FlowyError, _>(|| { for changeset in changesets { - GridViewRevisionSql::update(changeset, conn)?; + DatabaseViewRevisionSql::update(changeset, conn)?; } Ok(()) })?; @@ -77,7 +77,7 @@ impl RevisionDiskCache> for SQLiteDatabaseViewRevisionPersis rev_ids: Option>, ) -> Result<(), Self::Error> { let conn = &*self.pool.get().map_err(internal_error)?; - GridViewRevisionSql::delete(object_id, rev_ids, conn)?; + DatabaseViewRevisionSql::delete(object_id, rev_ids, conn)?; Ok(()) } @@ -89,22 +89,23 @@ impl RevisionDiskCache> for SQLiteDatabaseViewRevisionPersis ) -> Result<(), Self::Error> { let conn = self.pool.get().map_err(internal_error)?; conn.immediate_transaction::<_, FlowyError, _>(|| { - GridViewRevisionSql::delete(object_id, deleted_rev_ids, &conn)?; - GridViewRevisionSql::create(inserted_records, &conn)?; + DatabaseViewRevisionSql::delete(object_id, deleted_rev_ids, &conn)?; + DatabaseViewRevisionSql::create(inserted_records, &conn)?; Ok(()) }) } } -struct GridViewRevisionSql(); -impl GridViewRevisionSql { +struct DatabaseViewRevisionSql(); +impl DatabaseViewRevisionSql { fn create(revision_records: Vec, conn: &SqliteConnection) -> Result<(), FlowyError> { // Batch insert: https://diesel.rs/guides/all-about-inserts.html let records = revision_records .into_iter() .map(|record| { tracing::trace!( - "[GridViewRevisionSql] create revision: {}:{:?}", + "[{}] create revision: {}:{:?}", + std::any::type_name::(), record.revision.object_id, record.revision.rev_id ); @@ -132,7 +133,8 @@ impl GridViewRevisionSql { .filter(dsl::object_id.eq(changeset.object_id)); let _ = update(filter).set(dsl::state.eq(state)).execute(conn)?; tracing::debug!( - "[GridViewRevisionSql] update revision:{} state:to {:?}", + "[{}] update revision:{} state:to {:?}", + std::any::type_name::(), changeset.rev_id, changeset.state ); @@ -192,7 +194,8 @@ impl GridViewRevisionSql { if let Some(rev_ids) = rev_ids { tracing::trace!( - "[GridViewRevisionSql] Delete revision: {}:{:?}", + "[{}] Delete revision: {}:{:?}", + std::any::type_name::(), object_id, rev_ids ); @@ -200,7 +203,11 @@ impl GridViewRevisionSql { } let affected_row = sql.execute(conn)?; - tracing::trace!("[GridViewRevisionSql] Delete {} rows", affected_row); + tracing::trace!( + "[{}] Delete {} rows", + std::any::type_name::(), + affected_row + ); Ok(()) } } diff --git a/frontend/rust-lib/flowy-database/src/services/sort/controller.rs b/frontend/rust-lib/flowy-database/src/services/sort/controller.rs index 49e048754a..ab6ac9b721 100644 --- a/frontend/rust-lib/flowy-database/src/services/sort/controller.rs +++ b/frontend/rust-lib/flowy-database/src/services/sort/controller.rs @@ -63,12 +63,11 @@ impl SortController { } pub async fn close(&self) { - self - .task_scheduler - .write() - .await - .unregister_handler(&self.handler_id) - .await; + if let Ok(mut task_scheduler) = self.task_scheduler.try_write() { + // task_scheduler.unregister_handler(&self.handler_id).await; + } else { + tracing::error!("Try to get the lock of task_scheduler failed"); + } } pub async fn did_receive_row_changed(&self, row_id: &str) { diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/rev_sqlite/folder_rev_sqlite.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/rev_sqlite/folder_rev_sqlite.rs index 59df4f4c2a..de32507c4e 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/rev_sqlite/folder_rev_sqlite.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/rev_sqlite/folder_rev_sqlite.rs @@ -106,7 +106,8 @@ impl FolderRevisionSql { .into_iter() .map(|record| { tracing::trace!( - "[TextRevisionSql] create revision: {}:{:?}", + "[{}] create revision: {}:{:?}", + std::any::type_name::(), record.revision.object_id, record.revision.rev_id ); @@ -135,7 +136,8 @@ impl FolderRevisionSql { .filter(dsl::doc_id.eq(changeset.object_id)); let _ = update(filter).set(dsl::state.eq(state)).execute(conn)?; tracing::debug!( - "[TextRevisionSql] update revision:{} state:to {:?}", + "[{}] update revision:{} state:to {:?}", + std::any::type_name::(), changeset.rev_id, changeset.state ); @@ -193,7 +195,8 @@ impl FolderRevisionSql { if let Some(rev_ids) = rev_ids { tracing::trace!( - "[TextRevisionSql] Delete revision: {}:{:?}", + "[{}] Delete revision: {}:{:?}", + std::any::type_name::(), object_id, rev_ids ); @@ -201,7 +204,11 @@ impl FolderRevisionSql { } let affected_row = sql.execute(conn)?; - tracing::trace!("[TextRevisionSql] Delete {} rows", affected_row); + tracing::trace!( + "[{}] Delete {} rows", + std::any::type_name::(), + affected_row + ); Ok(()) } } diff --git a/frontend/rust-lib/flowy-task/src/scheduler.rs b/frontend/rust-lib/flowy-task/src/scheduler.rs index ee9e4d979a..ae61bb08bb 100644 --- a/frontend/rust-lib/flowy-task/src/scheduler.rs +++ b/frontend/rust-lib/flowy-task/src/scheduler.rs @@ -5,6 +5,7 @@ use anyhow::Error; use lib_infra::async_trait::async_trait; use lib_infra::future::BoxResultFuture; use lib_infra::ref_map::{RefCountHashMap, RefCountValue}; +use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; @@ -15,7 +16,7 @@ pub struct TaskDispatcher { queue: TaskQueue, store: TaskStore, timeout: Duration, - handlers: RefCountHashMap, + handlers: HashMap>, notifier: watch::Sender, pub(crate) notifier_rx: Option>, @@ -28,7 +29,7 @@ impl TaskDispatcher { queue: TaskQueue::new(), store: TaskStore::new(), timeout, - handlers: RefCountHashMap::new(), + handlers: HashMap::new(), notifier, notifier_rx: Some(notifier_rx), } @@ -39,13 +40,17 @@ impl TaskDispatcher { T: TaskHandler, { let handler_id = handler.handler_id().to_owned(); - self - .handlers - .insert(handler_id, RefCountTaskHandler(Arc::new(handler))); + self.handlers.insert(handler_id, Arc::new(handler)); } pub async fn unregister_handler>(&mut self, handler_id: T) { - self.handlers.remove(handler_id.as_ref()).await; + if let Some(handler) = self.handlers.remove(handler_id.as_ref()) { + tracing::trace!( + "{}:{} is unregistered", + handler.handler_name(), + handler.handler_id() + ); + } } pub fn stop(&mut self) { @@ -54,6 +59,7 @@ impl TaskDispatcher { self.store.clear(); } + #[tracing::instrument(level = "trace", skip_all)] pub(crate) async fn process_next_task(&mut self) -> Option<()> { let pending_task = self.queue.mut_head(|list| list.pop())?; let mut task = self.store.remove_task(&pending_task.id)?; @@ -69,25 +75,25 @@ impl TaskDispatcher { let content = task.content.take()?; if let Some(handler) = self.handlers.get(&task.handler_id) { task.set_state(TaskState::Processing); - tracing::trace!( - "Run {} task with content: {:?}", - handler.handler_name(), - content - ); + tracing::trace!("{} task is running", handler.handler_name(),); match tokio::time::timeout(self.timeout, handler.run(content)).await { Ok(result) => match result { - Ok(_) => task.set_state(TaskState::Done), + Ok(_) => { + tracing::trace!("{} task is done", handler.handler_name(),); + task.set_state(TaskState::Done) + }, Err(e) => { - tracing::error!("Process {} task failed: {:?}", handler.handler_name(), e); + tracing::error!("{} task is failed: {:?}", handler.handler_name(), e); task.set_state(TaskState::Failure); }, }, Err(e) => { - tracing::error!("Process {} task timeout: {:?}", handler.handler_name(), e); + tracing::error!("{} task is timeout: {:?}", handler.handler_name(), e); task.set_state(TaskState::Timeout); }, } } else { + tracing::trace!("{} is cancel", task.handler_id); task.set_state(TaskState::Cancel); } let _ = ret.send(task.into()); @@ -197,18 +203,3 @@ where (**self).run(content) } } -#[derive(Clone)] -struct RefCountTaskHandler(Arc); - -#[async_trait] -impl RefCountValue for RefCountTaskHandler { - async fn did_remove(&self) {} -} - -impl std::ops::Deref for RefCountTaskHandler { - type Target = Arc; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} From dcf8fd538dfcdfff91136a8ca773df8d31fda2ea Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 2 Mar 2023 20:28:46 +0800 Subject: [PATCH 009/117] chore: format code --- .../rust-lib/flowy-database/src/manager.rs | 39 ++++++++++--------- .../src/services/database_view/editor.rs | 11 +----- .../services/database_view/editor_manager.rs | 16 ++++---- .../src/services/filter/controller.rs | 11 +++--- .../src/services/sort/controller.rs | 2 +- frontend/rust-lib/flowy-task/src/scheduler.rs | 4 +- 6 files changed, 38 insertions(+), 45 deletions(-) diff --git a/frontend/rust-lib/flowy-database/src/manager.rs b/frontend/rust-lib/flowy-database/src/manager.rs index 5195f567de..db0d894efe 100644 --- a/frontend/rust-lib/flowy-database/src/manager.rs +++ b/frontend/rust-lib/flowy-database/src/manager.rs @@ -31,7 +31,7 @@ use flowy_task::TaskDispatcher; use revision_model::Revision; use std::sync::Arc; -use tokio::sync::{RwLock, RwLockWriteGuard, TryLockError}; +use tokio::sync::RwLock; pub trait DatabaseUser: Send + Sync { fn user_id(&self) -> Result; @@ -146,24 +146,25 @@ impl DatabaseManager { let database_info = self.database_ref_indexer.get_database_with_view(view_id)?; tracing::Span::current().record("database_id", &database_info.database_id); - match self.editors_by_database_id.try_write() { - Ok(mut write_guard) => { - if let Some(database_editor) = write_guard.remove(&database_info.database_id) { - database_editor.close_view_editor(view_id).await; - if database_editor.number_of_ref_views().await == 0 { - database_editor.dispose().await; - } else { - self - .editors_by_database_id - .write() - .await - .insert(database_info.database_id, database_editor); - } - } - }, - Err(_) => { - tracing::error!("Try to get the lock of editors_by_database_id failed"); - }, + // Create a temporary reference database_editor in case of holding the write lock + // of editors_by_database_id too long. + let database_editor = self + .editors_by_database_id + .write() + .await + .remove(&database_info.database_id); + + if let Some(database_editor) = database_editor { + database_editor.close_view_editor(view_id).await; + if database_editor.number_of_ref_views().await == 0 { + database_editor.dispose().await; + } else { + self + .editors_by_database_id + .write() + .await + .insert(database_info.database_id, database_editor); + } } Ok(()) diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs b/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs index e6918b9f50..96dd993e6c 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs @@ -28,9 +28,7 @@ use flowy_error::FlowyResult; use flowy_revision::RevisionManager; use flowy_sqlite::ConnectionPool; use flowy_task::TaskDispatcher; -use lib_infra::async_trait::async_trait; use lib_infra::future::Fut; -use lib_infra::ref_map::RefCountValue; use nanoid::nanoid; use revision_model::Revision; use std::borrow::Cow; @@ -182,8 +180,8 @@ impl DatabaseViewEditor { pub async fn close(&self) { self.rev_manager.generate_snapshot().await; self.rev_manager.close().await; - self.filter_controller.close().await; self.sort_controller.write().await.close().await; + // self.filter_controller.close().await; } pub async fn handle_block_event(&self, event: Cow<'_, DatabaseBlockEvent>) { @@ -869,13 +867,6 @@ pub(crate) async fn get_cells_for_field( Ok(cells) } -#[async_trait] -impl RefCountValue for DatabaseViewEditor { - async fn did_remove(&self) { - self.close().await; - } -} - async fn new_group_controller( user_id: String, view_id: String, diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs index 05975b1fb2..70881b4593 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs @@ -20,8 +20,8 @@ use flowy_error::FlowyResult; use flowy_revision::{RevisionManager, RevisionPersistence, RevisionPersistenceConfiguration}; use flowy_sqlite::ConnectionPool; use lib_infra::future::Fut; -use lib_infra::ref_map::RefCountHashMap; use std::borrow::Cow; +use std::collections::HashMap; use std::sync::Arc; use tokio::sync::{broadcast, RwLock}; @@ -29,7 +29,7 @@ use tokio::sync::{broadcast, RwLock}; pub struct DatabaseViews { user: Arc, delegate: Arc, - view_editors: Arc>>>, + view_editors: Arc>>>, cell_data_cache: AtomicCellDataCache, } @@ -40,7 +40,7 @@ impl DatabaseViews { cell_data_cache: AtomicCellDataCache, block_event_rx: broadcast::Receiver, ) -> FlowyResult { - let view_editors = Arc::new(RwLock::new(RefCountHashMap::default())); + let view_editors = Arc::new(RwLock::new(HashMap::default())); listen_on_database_block_event(block_event_rx, view_editors.clone()); Ok(Self { user, @@ -61,7 +61,9 @@ impl DatabaseViews { pub async fn close(&self, view_id: &str) { if let Ok(mut view_editors) = self.view_editors.try_write() { - view_editors.remove(view_id).await; + if let Some(view_editor) = view_editors.remove(view_id) { + view_editor.close().await; + } } else { tracing::error!("Try to get the lock of view_editors failed"); } @@ -273,7 +275,7 @@ impl DatabaseViews { pub async fn get_view_editor(&self, view_id: &str) -> FlowyResult> { debug_assert!(!view_id.is_empty()); if let Some(editor) = self.view_editors.read().await.get(view_id) { - return Ok(editor); + return Ok(editor.clone()); } tracing::trace!("{:p} create view:{} editor", self, view_id); @@ -346,7 +348,7 @@ pub async fn make_database_view_rev_manager( fn listen_on_database_block_event( mut block_event_rx: broadcast::Receiver, - view_editors: Arc>>>, + view_editors: Arc>>>, ) { tokio::spawn(async move { loop { @@ -358,7 +360,7 @@ fn listen_on_database_block_event( } else { Cow::Borrowed(&event) }; - for view_editor in view_editors.iter() { + for view_editor in view_editors { view_editor.handle_block_event(event.clone()).await; } } diff --git a/frontend/rust-lib/flowy-database/src/services/filter/controller.rs b/frontend/rust-lib/flowy-database/src/services/filter/controller.rs index aa0394e03d..0258d3b7b6 100644 --- a/frontend/rust-lib/flowy-database/src/services/filter/controller.rs +++ b/frontend/rust-lib/flowy-database/src/services/filter/controller.rs @@ -74,12 +74,11 @@ impl FilterController { } pub async fn close(&self) { - self - .task_scheduler - .write() - .await - .unregister_handler(&self.handler_id) - .await; + if let Ok(mut task_scheduler) = self.task_scheduler.try_write() { + task_scheduler.unregister_handler(&self.handler_id).await; + } else { + tracing::error!("Try to get the lock of task_scheduler failed"); + } } #[tracing::instrument(name = "schedule_filter_task", level = "trace", skip(self))] diff --git a/frontend/rust-lib/flowy-database/src/services/sort/controller.rs b/frontend/rust-lib/flowy-database/src/services/sort/controller.rs index ab6ac9b721..2abc7d517c 100644 --- a/frontend/rust-lib/flowy-database/src/services/sort/controller.rs +++ b/frontend/rust-lib/flowy-database/src/services/sort/controller.rs @@ -64,7 +64,7 @@ impl SortController { pub async fn close(&self) { if let Ok(mut task_scheduler) = self.task_scheduler.try_write() { - // task_scheduler.unregister_handler(&self.handler_id).await; + task_scheduler.unregister_handler(&self.handler_id).await; } else { tracing::error!("Try to get the lock of task_scheduler failed"); } diff --git a/frontend/rust-lib/flowy-task/src/scheduler.rs b/frontend/rust-lib/flowy-task/src/scheduler.rs index ae61bb08bb..5e24114d3f 100644 --- a/frontend/rust-lib/flowy-task/src/scheduler.rs +++ b/frontend/rust-lib/flowy-task/src/scheduler.rs @@ -2,9 +2,9 @@ use crate::queue::TaskQueue; use crate::store::TaskStore; use crate::{Task, TaskContent, TaskId, TaskState}; use anyhow::Error; -use lib_infra::async_trait::async_trait; + use lib_infra::future::BoxResultFuture; -use lib_infra::ref_map::{RefCountHashMap, RefCountValue}; + use std::collections::HashMap; use std::sync::Arc; use std::time::Duration; From 9b0fccbdda9d25ed715662bc6397953a7f42f06b Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 3 Mar 2023 10:04:53 +0800 Subject: [PATCH 010/117] chore: update tokio version --- .../src-tauri/.cargo/config.toml | 2 + frontend/appflowy_tauri/src-tauri/Cargo.lock | 461 ++++++++++++--- frontend/appflowy_tauri/src-tauri/Cargo.toml | 2 +- frontend/rust-lib/.cargo/config.toml | 4 +- frontend/rust-lib/Cargo.lock | 535 +++++++++++++++--- frontend/rust-lib/dart-ffi/Cargo.toml | 12 +- frontend/rust-lib/flowy-ast/Cargo.toml | 4 +- .../rust-lib/flowy-client-sync/Cargo.toml | 8 +- frontend/rust-lib/flowy-codegen/Cargo.toml | 14 +- frontend/rust-lib/flowy-core/Cargo.toml | 127 ++--- frontend/rust-lib/flowy-core/src/lib.rs | 3 + frontend/rust-lib/flowy-database/Cargo.toml | 28 +- .../src/services/database_view/editor.rs | 8 +- .../src/services/filter/controller.rs | 6 + .../src/services/sort/controller.rs | 6 + frontend/rust-lib/flowy-derive/Cargo.toml | 10 +- frontend/rust-lib/flowy-document/Cargo.toml | 20 +- frontend/rust-lib/flowy-error/Cargo.toml | 6 +- frontend/rust-lib/flowy-folder/Cargo.toml | 12 +- frontend/rust-lib/flowy-net/Cargo.toml | 14 +- .../rust-lib/flowy-notification/Cargo.toml | 4 +- frontend/rust-lib/flowy-revision/Cargo.toml | 12 +- frontend/rust-lib/flowy-sqlite/Cargo.toml | 46 +- frontend/rust-lib/flowy-task/Cargo.toml | 6 +- frontend/rust-lib/flowy-test/Cargo.toml | 16 +- frontend/rust-lib/flowy-user/Cargo.toml | 10 +- frontend/rust-lib/lib-dispatch/Cargo.toml | 18 +- frontend/rust-lib/lib-log/Cargo.toml | 10 +- shared-lib/database-model/Cargo.toml | 4 +- .../flowy-client-network-config/Cargo.toml | 2 +- shared-lib/flowy-client-ws/Cargo.toml | 4 +- shared-lib/flowy-server-sync/Cargo.toml | 10 +- shared-lib/flowy-sync/Cargo.toml | 2 +- shared-lib/lib-infra/Cargo.toml | 8 +- shared-lib/lib-ot/Cargo.toml | 6 +- shared-lib/lib-ws/Cargo.toml | 18 +- shared-lib/revision-model/Cargo.toml | 2 +- shared-lib/user-model/Cargo.toml | 12 +- shared-lib/ws-model/Cargo.toml | 2 +- 39 files changed, 1084 insertions(+), 390 deletions(-) create mode 100644 frontend/appflowy_tauri/src-tauri/.cargo/config.toml diff --git a/frontend/appflowy_tauri/src-tauri/.cargo/config.toml b/frontend/appflowy_tauri/src-tauri/.cargo/config.toml new file mode 100644 index 0000000000..bff29e6e17 --- /dev/null +++ b/frontend/appflowy_tauri/src-tauri/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["--cfg", "tokio_unstable"] diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 84e76e18ec..85ab5aa964 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -106,19 +106,20 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "async-stream" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" dependencies = [ "async-stream-impl", "futures-core", + "pin-project-lite", ] [[package]] name = "async-stream-impl" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" dependencies = [ "proc-macro2", "quote", @@ -127,9 +128,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.61" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705339e0e4a9690e2908d2b3d049d85682cf19fbd5782494498fbf7003a6a282" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -172,6 +173,52 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "axum" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fb79c228270dcf2426e74864cabc94babb5dbab01a4314e702d2f16540e1591" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa 1.0.5", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-http", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.67" @@ -193,6 +240,12 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + [[package]] name = "bincode" version = "1.3.3" @@ -249,19 +302,19 @@ dependencies = [ [[package]] name = "borsh" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +checksum = "40f9ca3698b2e4cb7c15571db0abc5551dca417a21ae8140460b50309bb2cc62" dependencies = [ "borsh-derive", - "hashbrown 0.11.2", + "hashbrown", ] [[package]] name = "borsh-derive" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +checksum = "598b3eacc6db9c3ee57b22707ad8f6a8d2f6d442bfe24ffeb8cbb70ca59e6a35" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -272,9 +325,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" dependencies = [ "proc-macro2", "quote", @@ -283,9 +336,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" dependencies = [ "proc-macro2", "quote", @@ -364,9 +417,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" dependencies = [ "serde", ] @@ -577,7 +630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3" dependencies = [ "lazy_static", - "nom", + "nom 5.1.2", "serde", "yaml-rust", ] @@ -597,6 +650,42 @@ dependencies = [ "winapi", ] +[[package]] +name = "console-api" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57ff02e8ad8e06ab9731d5dc72dc23bef9200778eae1a89d555d8c42e5d4a86" +dependencies = [ + "prost", + "prost-types", + "tonic", + "tracing-core", +] + +[[package]] +name = "console-subscriber" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a3a81dfaf6b66bce5d159eddae701e3a002f194d378cbf7be5f053c281d9be" +dependencies = [ + "console-api", + "crossbeam-channel", + "crossbeam-utils", + "futures", + "hdrhistogram", + "humantime", + "prost-types", + "serde", + "serde_json", + "thread_local", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "tracing-core", + "tracing-subscriber 0.3.16", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -698,9 +787,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", ] @@ -844,7 +933,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" dependencies = [ "cfg-if", - "hashbrown 0.12.3", + "hashbrown", "lock_api", "once_cell", "parking_lot_core", @@ -1107,7 +1196,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall 0.2.16", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1208,6 +1297,7 @@ name = "flowy-core" version = "0.1.0" dependencies = [ "bytes", + "console-subscriber", "database-model", "flowy-client-ws", "flowy-database", @@ -1630,9 +1720,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -1645,9 +1735,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1655,15 +1745,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -1672,15 +1762,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -1689,21 +1779,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -2049,15 +2139,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -2067,6 +2148,19 @@ dependencies = [ "ahash", ] +[[package]] +name = "hdrhistogram" +version = "7.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" +dependencies = [ + "base64 0.13.1", + "byteorder", + "flate2", + "nom 7.1.3", + "num-traits", +] + [[package]] name = "heck" version = "0.3.3" @@ -2143,6 +2237,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" +[[package]] +name = "http-range-header" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + [[package]] name = "httparse" version = "1.8.0" @@ -2161,6 +2261,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.23" @@ -2185,6 +2291,18 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -2296,7 +2414,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown 0.12.3", + "hashbrown", "serde", ] @@ -2670,6 +2788,12 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "matchit" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" + [[package]] name = "md5" version = "0.7.0" @@ -2727,6 +2851,12 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -2745,7 +2875,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2826,6 +2956,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2936,9 +3076,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "opaque-debug" @@ -2953,7 +3093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2078c0039e6a54a0c42c28faa984e115fb4c2d5bf2208f77d1961002df8576f8" dependencies = [ "pathdiff", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3062,7 +3202,7 @@ dependencies = [ "libc", "redox_syscall 0.2.16", "smallvec", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3317,7 +3457,7 @@ version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd39bc6cdc9355ad1dc5eeedefee696bb35c34caf21768741e81826c0bbd7225" dependencies = [ - "base64", + "base64 0.13.1", "indexmap", "line-wrap", "serde", @@ -3401,13 +3541,45 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88" +dependencies = [ + "prost", +] + [[package]] name = "protobuf" version = "2.28.0" @@ -3719,11 +3891,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ - "base64", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", @@ -3771,7 +3943,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" dependencies = [ "bytecheck", - "hashbrown 0.12.3", + "hashbrown", "ptr_meta", "rend", "rkyv_derive", @@ -3791,9 +3963,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.27.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9" +checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" dependencies = [ "arrayvec 0.7.2", "borsh", @@ -3884,7 +4056,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -4298,15 +4470,21 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-deps" version = "5.0.0" @@ -4459,7 +4637,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14388d484b6b1b5dc0f6a7d6cc6433b3b230bec85eaa576adcdf3f9fafa49251" dependencies = [ - "base64", + "base64 0.13.1", "brotli", "ico", "json-patch", @@ -4728,9 +4906,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.24.1" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9f76183f91ecfb55e1d7d5602bd1d979e38a3a522fe900241cf195624d67ae" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ "autocfg", "bytes", @@ -4743,7 +4921,18 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "tracing", + "windows-sys 0.45.0", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", ] [[package]] @@ -4767,6 +4956,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-tungstenite" version = "0.15.0" @@ -4796,13 +4996,90 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] +[[package]] +name = "tonic" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.13.1", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "prost-derive", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project", + "pin-project-lite", + "rand 0.8.5", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -4871,6 +5148,16 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "tracing-log" version = "0.1.3" @@ -4953,7 +5240,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5" dependencies = [ - "base64", + "base64 0.13.1", "byteorder", "bytes", "http", @@ -5459,6 +5746,30 @@ dependencies = [ "windows_x86_64_msvc 0.42.1", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", +] + [[package]] name = "windows-tokens" version = "0.39.0" @@ -5561,7 +5872,7 @@ version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c1ad8e2424f554cc5bdebe8aa374ef5b433feff817aebabca0389961fc7ef98" dependencies = [ - "base64", + "base64 0.13.1", "block", "cocoa", "core-graphics", diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.toml b/frontend/appflowy_tauri/src-tauri/Cargo.toml index 42c5cd15b7..04fccca1aa 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.toml +++ b/frontend/appflowy_tauri/src-tauri/Cargo.toml @@ -18,7 +18,7 @@ serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } tauri = { version = "1.2", features = ["shell-open"] } tauri-utils = "1.2" -bytes = { version = "1.0" } +bytes = { version = "1.4" } tracing = { version = "0.1", features = ["log"] } lib-dispatch = { path = "../../rust-lib/lib-dispatch", features = ["use_serde"] } flowy-core = { path = "../../rust-lib/flowy-core", features = ["rev-sqlite","ts"] } diff --git a/frontend/rust-lib/.cargo/config.toml b/frontend/rust-lib/.cargo/config.toml index 5be8246f16..f6792d6cbd 100644 --- a/frontend/rust-lib/.cargo/config.toml +++ b/frontend/rust-lib/.cargo/config.toml @@ -1,5 +1,5 @@ -#[build] -#target-dir = "./bin" +[build] +rustflags = ["--cfg", "tokio_unstable"] [target.x86_64-apple-darwin] rustflags=["-C", "link-arg=-mmacosx-version-min=10.11"] diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index f6ec311c5a..2052c1707c 100644 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -85,19 +85,20 @@ checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "async-stream" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" dependencies = [ "async-stream-impl", "futures-core", + "pin-project-lite", ] [[package]] name = "async-stream-impl" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" dependencies = [ "proc-macro2", "quote", @@ -106,9 +107,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.61" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705339e0e4a9690e2908d2b3d049d85682cf19fbd5782494498fbf7003a6a282" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -143,9 +144,55 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "axum" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fb79c228270dcf2426e74864cabc94babb5dbab01a4314e702d2f16540e1591" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa 1.0.5", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-http", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] [[package]] name = "backtrace" @@ -168,6 +215,21 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" + +[[package]] +name = "basic-toml" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e819b667739967cd44d308b8c7b71305d8bb0729ac44a248aa08f33d01950b4" +dependencies = [ + "serde", +] + [[package]] name = "bincode" version = "1.3.3" @@ -218,19 +280,19 @@ dependencies = [ [[package]] name = "borsh" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +checksum = "40f9ca3698b2e4cb7c15571db0abc5551dca417a21ae8140460b50309bb2cc62" dependencies = [ "borsh-derive", - "hashbrown 0.11.2", + "hashbrown", ] [[package]] name = "borsh-derive" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +checksum = "598b3eacc6db9c3ee57b22707ad8f6a8d2f6d442bfe24ffeb8cbb70ca59e6a35" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -241,9 +303,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" dependencies = [ "proc-macro2", "quote", @@ -252,9 +314,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" dependencies = [ "proc-macro2", "quote", @@ -318,9 +380,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" dependencies = [ "serde", ] @@ -380,15 +442,6 @@ dependencies = [ "phf_codegen", ] -[[package]] -name = "claim" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81099d6bb72e1df6d50bb2347224b666a670912bb7f06dbe867a4a070ab3ce8" -dependencies = [ - "autocfg", -] - [[package]] name = "clap" version = "2.34.0" @@ -455,7 +508,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3" dependencies = [ "lazy_static", - "nom", + "nom 5.1.2", "serde", "yaml-rust", ] @@ -475,6 +528,42 @@ dependencies = [ "winapi", ] +[[package]] +name = "console-api" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57ff02e8ad8e06ab9731d5dc72dc23bef9200778eae1a89d555d8c42e5d4a86" +dependencies = [ + "prost", + "prost-types", + "tonic", + "tracing-core", +] + +[[package]] +name = "console-subscriber" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22a3a81dfaf6b66bce5d159eddae701e3a002f194d378cbf7be5f053c281d9be" +dependencies = [ + "console-api", + "crossbeam-channel", + "crossbeam-utils", + "futures", + "hdrhistogram", + "humantime", + "prost-types", + "serde", + "serde_json", + "thread_local", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "tracing-core", + "tracing-subscriber 0.3.16", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -506,6 +595,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + [[package]] name = "criterion" version = "0.3.6" @@ -578,9 +676,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if", ] @@ -908,6 +1006,16 @@ dependencies = [ "instant", ] +[[package]] +name = "flate2" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + [[package]] name = "flowy-ast" version = "0.1.0" @@ -996,6 +1104,7 @@ name = "flowy-core" version = "0.1.0" dependencies = [ "bytes", + "console-subscriber", "database-model", "flowy-client-ws", "flowy-database", @@ -1129,7 +1238,7 @@ dependencies = [ "strum_macros", "tokio", "tracing", - "tracing-subscriber", + "tracing-subscriber 0.2.25", "unicode-segmentation", "url", "ws-model", @@ -1365,7 +1474,6 @@ name = "flowy-test" version = "0.1.0" dependencies = [ "bytes", - "claim", "fake", "flowy-client-sync", "flowy-core", @@ -1462,9 +1570,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -1477,9 +1585,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1487,15 +1595,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -1504,15 +1612,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -1521,21 +1629,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -1652,15 +1760,6 @@ version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1670,6 +1769,19 @@ dependencies = [ "ahash", ] +[[package]] +name = "hdrhistogram" +version = "7.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" +dependencies = [ + "base64 0.13.1", + "byteorder", + "flate2", + "nom 7.1.3", + "num-traits", +] + [[package]] name = "heck" version = "0.3.3" @@ -1729,6 +1841,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "http-range-header" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" + [[package]] name = "httparse" version = "1.8.0" @@ -1747,6 +1865,12 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" version = "0.14.23" @@ -1771,6 +1895,18 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -1859,7 +1995,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", - "hashbrown 0.12.3", + "hashbrown", "serde", ] @@ -1985,7 +2121,7 @@ dependencies = [ "tracing-bunyan-formatter", "tracing-core", "tracing-log", - "tracing-subscriber", + "tracing-subscriber 0.2.25", ] [[package]] @@ -2089,12 +2225,27 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + [[package]] name = "matches" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +[[package]] +name = "matchit" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" + [[package]] name = "md5" version = "0.7.0" @@ -2143,6 +2294,12 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -2161,7 +2318,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2202,6 +2359,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -2242,9 +2409,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" @@ -2374,7 +2541,7 @@ dependencies = [ "libc", "redox_syscall 0.2.16", "smallvec", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2639,6 +2806,38 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "prost-types" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88" +dependencies = [ + "prost", +] + [[package]] name = "protobuf" version = "2.28.0" @@ -2952,11 +3151,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ - "base64", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", @@ -3004,7 +3203,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" dependencies = [ "bytecheck", - "hashbrown 0.12.3", + "hashbrown", "ptr_meta", "rend", "rkyv_derive", @@ -3024,9 +3223,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.27.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9" +checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" dependencies = [ "arrayvec 0.7.2", "borsh", @@ -3065,6 +3264,12 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" + [[package]] name = "rusty-money" version = "0.4.1" @@ -3096,7 +3301,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -3366,15 +3571,21 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "tempfile" version = "3.3.0" @@ -3517,22 +3728,33 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.2" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ + "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", - "once_cell", "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "winapi", + "tracing", + "windows-sys 0.45.0", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", ] [[package]] @@ -3556,6 +3778,17 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-tungstenite" version = "0.15.0" @@ -3585,13 +3818,90 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] +[[package]] +name = "tonic" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.13.1", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "prost-derive", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project", + "pin-project-lite", + "rand 0.8.5", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-range-header", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.2" @@ -3619,7 +3929,7 @@ checksum = "9965507e507f12c8901432a33e31131222abac31edd90cabbcf85cf544b7127a" dependencies = [ "chrono", "crossbeam-channel", - "tracing-subscriber", + "tracing-subscriber 0.2.25", ] [[package]] @@ -3647,7 +3957,7 @@ dependencies = [ "tracing", "tracing-core", "tracing-log", - "tracing-subscriber", + "tracing-subscriber 0.2.25", ] [[package]] @@ -3660,6 +3970,16 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + [[package]] name = "tracing-log" version = "0.1.3" @@ -3690,7 +4010,7 @@ dependencies = [ "ansi_term", "chrono", "lazy_static", - "matchers", + "matchers 0.0.1", "regex", "serde", "serde_json", @@ -3703,6 +4023,21 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "tracing-subscriber" +version = "0.3.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +dependencies = [ + "matchers 0.1.0", + "once_cell", + "regex", + "sharded-slab", + "thread_local", + "tracing", + "tracing-core", +] + [[package]] name = "try-lock" version = "0.2.4" @@ -3711,17 +4046,17 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "trybuild" -version = "1.0.75" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1212c215a87a183687a7cc7065901b1a98da6b37277d51a1b5faedbb4efd4f3" +checksum = "a44da5a6f2164c8e14d3bbc0657d69c5966af9f5f6930d4f600b1f5c4a673413" dependencies = [ + "basic-toml", "glob", "once_cell", "serde", "serde_derive", "serde_json", "termcolor", - "toml", ] [[package]] @@ -3730,7 +4065,7 @@ version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0b2d8558abd2e276b0a8df5c05a2ec762609344191e5fd23e292c910e9165b5" dependencies = [ - "base64", + "base64 0.13.1", "byteorder", "bytes", "http", @@ -4083,6 +4418,30 @@ dependencies = [ "windows_x86_64_msvc", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.1" diff --git a/frontend/rust-lib/dart-ffi/Cargo.toml b/frontend/rust-lib/dart-ffi/Cargo.toml index 774749d96e..7f7a2af45f 100644 --- a/frontend/rust-lib/dart-ffi/Cargo.toml +++ b/frontend/rust-lib/dart-ffi/Cargo.toml @@ -13,14 +13,14 @@ crate-type = ["staticlib"] [dependencies] allo-isolate = { version = "^0.1", features = ["catch-unwind"] } -byteorder = { version = "1.3.4" } -protobuf = { version = "2.20.0" } -tokio = { version = "1", features = ["rt", "rt-multi-thread"] } -log = "0.4.14" +byteorder = { version = "1.4.3" } +protobuf = { version = "2.28.0" } +tokio = { version = "1.26", features = ["rt", "rt-multi-thread"] } +log = "0.4.17" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0" } -bytes = { version = "1.0" } -crossbeam-utils = "0.8.7" +bytes = { version = "1.4" } +crossbeam-utils = "0.8.15" lazy_static = "1.4.0" parking_lot = "0.12.1" tracing = { version = "0.1", features = ["log"] } diff --git a/frontend/rust-lib/flowy-ast/Cargo.toml b/frontend/rust-lib/flowy-ast/Cargo.toml index 7af2d51468..87162bf533 100644 --- a/frontend/rust-lib/flowy-ast/Cargo.toml +++ b/frontend/rust-lib/flowy-ast/Cargo.toml @@ -6,6 +6,6 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -syn = { version = "1.0.60", features = ["extra-traits", "parsing", "derive", "full"]} +syn = { version = "1.0.109", features = ["extra-traits", "parsing", "derive", "full"]} quote = "1.0" -proc-macro2 = "1.0" \ No newline at end of file +proc-macro2 = "1.0" diff --git a/frontend/rust-lib/flowy-client-sync/Cargo.toml b/frontend/rust-lib/flowy-client-sync/Cargo.toml index 5168f98839..137af96835 100644 --- a/frontend/rust-lib/flowy-client-sync/Cargo.toml +++ b/frontend/rust-lib/flowy-client-sync/Cargo.toml @@ -14,14 +14,14 @@ database-model = { path = "../../../shared-lib/database-model" } revision-model = { path = "../../../shared-lib/revision-model" } document-model = { path = "../../../shared-lib/document-model" } flowy-sync = { path = "../../../shared-lib/flowy-sync" } -bytes = "1.0" -tokio = { version = "1", features = ["full"] } +bytes = "1.4" +tokio = { version = "1.26", features = ["full"] } serde = { version = "1.0", features = ["derive", "rc"] } serde_json = {version = "1.0"} dissimilar = "1.0" tracing = { version = "0.1", features = ["log"] } -url = "2.2" +url = "2.3" strum = "0.21" strum_macros = "0.21" -chrono = "0.4.19" +chrono = "0.4.23" parking_lot = "0.12.1" diff --git a/frontend/rust-lib/flowy-codegen/Cargo.toml b/frontend/rust-lib/flowy-codegen/Cargo.toml index 40143cfbdb..6121de6edd 100644 --- a/frontend/rust-lib/flowy-codegen/Cargo.toml +++ b/frontend/rust-lib/flowy-codegen/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -log = "0.4.14" +log = "0.4.17" serde = { version = "1.0", features = ["derive"]} serde_json = "1.0" flowy-ast = { path = "../flowy-ast"} @@ -15,16 +15,16 @@ quote = "1.0" cmd_lib = { version = "1.3.0", optional = true } protoc-rust = { version = "2", optional = true } walkdir = { version = "2", optional = true } -similar = { version = "1.2.2", optional = true } -syn = { version = "1.0.60", features = ["extra-traits", "parsing", "derive", "full"] } +similar = { version = "1.3.0", optional = true } +syn = { version = "1.0.109", features = ["extra-traits", "parsing", "derive", "full"] } fancy-regex = { version = "0.10.0", optional = true } lazy_static = { version = "1.4.0", optional = true } -tera = { version = "1.5.0", optional = true} +tera = { version = "1.17.1", optional = true} itertools = { version = "0.10", optional = true } phf = { version = "0.8.0", features = ["macros"], optional = true } -console = {version = "0.14.0", optional = true} +console = {version = "0.14.1", optional = true} protoc-bin-vendored = { version = "3.0", optional = true } -toml = {version = "0.5.8", optional = true} +toml = {version = "0.5.11", optional = true} @@ -47,4 +47,4 @@ proto_gen = [ dart_event = ["walkdir", "tera", ] dart = ["proto_gen", "dart_event"] ts_event = ["walkdir", "tera", ] -ts = ["proto_gen", "ts_event"] \ No newline at end of file +ts = ["proto_gen", "ts_event"] diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index 81cba6ff23..c36c635fe3 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -1,63 +1,64 @@ -[package] -name = "flowy-core" -version = "0.1.0" -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -lib-dispatch = { path = "../lib-dispatch" } -lib-log = { path = "../lib-log" } -flowy-user = { path = "../flowy-user" } -flowy-net = { path = "../flowy-net" } -flowy-folder = { path = "../flowy-folder" } -flowy-database = { path = "../flowy-database" } -database-model = { path = "../../../shared-lib/database-model" } -user-model = { path = "../../../shared-lib/user-model" } -flowy-client-ws = { path = "../../../shared-lib/flowy-client-ws" } -flowy-sqlite = { path = "../flowy-sqlite", optional = true } -flowy-document = { path = "../flowy-document" } -flowy-revision = { path = "../flowy-revision" } -flowy-error = { path = "../flowy-error", features = ["adaptor_ws"] } -flowy-task = { path = "../flowy-task" } - -tracing = { version = "0.1", features = ["log"] } -futures-core = { version = "0.3", default-features = false } -bytes = "1.0" -tokio = { version = "1", features = ["rt"] } -parking_lot = "0.12.1" - -revision-model = { path = "../../../shared-lib/revision-model" } -ws-model = { path = "../../../shared-lib/ws-model" } -lib-ws = { path = "../../../shared-lib/lib-ws" } -lib-infra = { path = "../../../shared-lib/lib-infra" } -serde = "1.0" -serde_json = "1.0" - -[features] -default = ["rev-sqlite"] -http_sync = ["flowy-folder/cloud_sync", "flowy-document/cloud_sync"] -native_sync = ["flowy-folder/cloud_sync", "flowy-document/cloud_sync"] -use_bunyan = ["lib-log/use_bunyan"] -dart = [ - "flowy-user/dart", - "flowy-net/dart", - "flowy-folder/dart", - "flowy-database/dart", - "flowy-document/dart", -] -ts = [ - "flowy-user/ts", - "flowy-net/ts", - "flowy-folder/ts", - "flowy-database/ts", - "flowy-document/ts", -] -rev-sqlite = [ - "flowy-sqlite", - "flowy-user/rev-sqlite", - "flowy-folder/rev-sqlite", - "flowy-database/rev-sqlite", - "flowy-document/rev-sqlite", -] -openssl_vendored = ["flowy-sqlite/openssl_vendored"] +[package] +name = "flowy-core" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +lib-dispatch = { path = "../lib-dispatch" } +lib-log = { path = "../lib-log" } +flowy-user = { path = "../flowy-user" } +flowy-net = { path = "../flowy-net" } +flowy-folder = { path = "../flowy-folder" } +flowy-database = { path = "../flowy-database" } +database-model = { path = "../../../shared-lib/database-model" } +user-model = { path = "../../../shared-lib/user-model" } +flowy-client-ws = { path = "../../../shared-lib/flowy-client-ws" } +flowy-sqlite = { path = "../flowy-sqlite", optional = true } +flowy-document = { path = "../flowy-document" } +flowy-revision = { path = "../flowy-revision" } +flowy-error = { path = "../flowy-error", features = ["adaptor_ws"] } +flowy-task = { path = "../flowy-task" } + +tracing = { version = "0.1", features = ["log"] } +futures-core = { version = "0.3", default-features = false } +bytes = "1.4" +tokio = { version = "1.26", features = ["full", "tracing"] } +console-subscriber = "0.1.8" +parking_lot = "0.12.1" + +revision-model = { path = "../../../shared-lib/revision-model" } +ws-model = { path = "../../../shared-lib/ws-model" } +lib-ws = { path = "../../../shared-lib/lib-ws" } +lib-infra = { path = "../../../shared-lib/lib-infra" } +serde = "1.0" +serde_json = "1.0" + +[features] +default = ["rev-sqlite"] +http_sync = ["flowy-folder/cloud_sync", "flowy-document/cloud_sync"] +native_sync = ["flowy-folder/cloud_sync", "flowy-document/cloud_sync"] +use_bunyan = ["lib-log/use_bunyan"] +dart = [ + "flowy-user/dart", + "flowy-net/dart", + "flowy-folder/dart", + "flowy-database/dart", + "flowy-document/dart", +] +ts = [ + "flowy-user/ts", + "flowy-net/ts", + "flowy-folder/ts", + "flowy-database/ts", + "flowy-document/ts", +] +rev-sqlite = [ + "flowy-sqlite", + "flowy-user/rev-sqlite", + "flowy-folder/rev-sqlite", + "flowy-database/rev-sqlite", + "flowy-document/rev-sqlite", +] +openssl_vendored = ["flowy-sqlite/openssl_vendored"] diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index 17c21a7052..70cf58fb5f 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -102,6 +102,7 @@ fn create_log_filter(level: String, with_crates: Vec) -> String { filters.push(format!("dart_ffi={}", "info")); filters.push(format!("flowy_sqlite={}", "info")); filters.push(format!("flowy_net={}", "info")); + filters.push(format!("tokio=trace,runtime=trace")); filters.join(",") } @@ -121,6 +122,8 @@ pub struct AppFlowyCore { impl AppFlowyCore { pub fn new(config: AppFlowyCoreConfig) -> Self { + // console_subscriber::init(); + init_log(&config); init_kv(&config.storage_path); tracing::debug!("🔥 {:?}", config); diff --git a/frontend/rust-lib/flowy-database/Cargo.toml b/frontend/rust-lib/flowy-database/Cargo.toml index 9bc9140769..ec686c098e 100644 --- a/frontend/rust-lib/flowy-database/Cargo.toml +++ b/frontend/rust-lib/flowy-database/Cargo.toml @@ -24,28 +24,28 @@ anyhow = "1.0" strum = "0.21" strum_macros = "0.21" tracing = { version = "0.1", features = ["log"] } -protobuf = {version = "2.18.0"} -rust_decimal = "1.8.1" -rusty-money = {version = "0.4.0", features = ["iso"]} +protobuf = {version = "2.28.0"} +rust_decimal = "1.28.1" +rusty-money = {version = "0.4.1", features = ["iso"]} lazy_static = "1.4.0" -chrono = "0.4.19" +chrono = "0.4.23" nanoid = "0.4.0" -bytes = { version = "1.0" } +bytes = { version = "1.4" } diesel = {version = "1.4.8", features = ["sqlite"]} dashmap = "5" -tokio = {version = "1", features = ["sync"]} -rayon = "1.5.2" +tokio = { version = "1.26", features = ["sync"]} +rayon = "1.6.1" serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0"} serde_repr = "0.1" -indexmap = {version = "1.9.1", features = ["serde"]} +indexmap = {version = "1.9.2", features = ["serde"]} fancy-regex = "0.10.0" -regex = "1.5.6" +regex = "1.7.1" url = { version = "2"} -futures = "0.3.15" -atomic_refcell = "0.1.8" -crossbeam-utils = "0.8.7" -async-stream = "0.3.2" +futures = "0.3.26" +atomic_refcell = "0.1.9" +crossbeam-utils = "0.8.15" +async-stream = "0.3.4" parking_lot = "0.12.1" [dev-dependencies] @@ -60,4 +60,4 @@ default = ["rev-sqlite"] rev-sqlite = ["flowy-sqlite"] dart = ["flowy-codegen/dart", "flowy-notification/dart"] ts = ["flowy-codegen/ts", "flowy-notification/ts"] -flowy_unit_test = ["flowy-revision/flowy_unit_test"] \ No newline at end of file +flowy_unit_test = ["flowy-revision/flowy_unit_test"] diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs b/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs index 96dd993e6c..67270def56 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/editor.rs @@ -83,6 +83,12 @@ pub struct DatabaseViewEditor { pub notifier: DatabaseViewChangedNotifier, } +impl Drop for DatabaseViewEditor { + fn drop(&mut self) { + tracing::trace!("Drop {}", std::any::type_name::()); + } +} + impl DatabaseViewEditor { pub async fn from_pad( user_id: &str, @@ -181,7 +187,7 @@ impl DatabaseViewEditor { self.rev_manager.generate_snapshot().await; self.rev_manager.close().await; self.sort_controller.write().await.close().await; - // self.filter_controller.close().await; + self.filter_controller.close().await; } pub async fn handle_block_event(&self, event: Cow<'_, DatabaseBlockEvent>) { diff --git a/frontend/rust-lib/flowy-database/src/services/filter/controller.rs b/frontend/rust-lib/flowy-database/src/services/filter/controller.rs index 0258d3b7b6..37ec5eb90f 100644 --- a/frontend/rust-lib/flowy-database/src/services/filter/controller.rs +++ b/frontend/rust-lib/flowy-database/src/services/filter/controller.rs @@ -46,6 +46,12 @@ pub struct FilterController { notifier: DatabaseViewChangedNotifier, } +impl Drop for FilterController { + fn drop(&mut self) { + tracing::trace!("Drop {}", std::any::type_name::()); + } +} + impl FilterController { pub async fn new( view_id: &str, diff --git a/frontend/rust-lib/flowy-database/src/services/sort/controller.rs b/frontend/rust-lib/flowy-database/src/services/sort/controller.rs index 2abc7d517c..dba5d7916b 100644 --- a/frontend/rust-lib/flowy-database/src/services/sort/controller.rs +++ b/frontend/rust-lib/flowy-database/src/services/sort/controller.rs @@ -37,6 +37,12 @@ pub struct SortController { notifier: DatabaseViewChangedNotifier, } +impl Drop for SortController { + fn drop(&mut self) { + tracing::trace!("Drop {}", std::any::type_name::()); + } +} + impl SortController { pub fn new( view_id: &str, diff --git a/frontend/rust-lib/flowy-derive/Cargo.toml b/frontend/rust-lib/flowy-derive/Cargo.toml index 6af5183bfd..a363dbc952 100644 --- a/frontend/rust-lib/flowy-derive/Cargo.toml +++ b/frontend/rust-lib/flowy-derive/Cargo.toml @@ -14,7 +14,7 @@ name = "tests" path = "tests/progress.rs" [dependencies] -syn = { version = "1.0.60", features = ["extra-traits", "visit"] } +syn = { version = "1.0.109", features = ["extra-traits", "visit"] } quote = "1.0" proc-macro2 = "1.0" flowy-ast = { path = "../flowy-ast" } @@ -22,9 +22,9 @@ lazy_static = {version = "1.4.0"} dashmap = "5" flowy-codegen = { path = "../flowy-codegen"} serde_json = "1.0" -walkdir = "2.3.1" +walkdir = "2.3.2" [dev-dependencies] -tokio = { version = "1", features = ["full"] } -trybuild = "1.0.40" -log = "0.4.11" +tokio = { version = "1.26", features = ["full"] } +trybuild = "1.0.77" +log = "0.4.17" diff --git a/frontend/rust-lib/flowy-document/Cargo.toml b/frontend/rust-lib/flowy-document/Cargo.toml index 9f20d7cea4..2ddf6cb1fb 100644 --- a/frontend/rust-lib/flowy-document/Cargo.toml +++ b/frontend/rust-lib/flowy-document/Cargo.toml @@ -25,29 +25,29 @@ flowy-notification = { path = "../flowy-notification" } diesel = {version = "1.4.8", features = ["sqlite"]} diesel_derives = {version = "1.4.1", features = ["sqlite"]} -protobuf = {version = "2.18.0"} -tokio = {version = "1", features = ["sync"]} +protobuf = {version = "2.28.0"} +tokio = { version = "1.26", features = ["sync"]} tracing = { version = "0.1", features = ["log"] } -bytes = { version = "1.1" } +bytes = { version = "1.4" } md5 = "0.7.0" strum = "0.21" strum_macros = "0.21" dashmap = "5" -url = "2.2" +url = "2.3" serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0"} -chrono = "0.4.19" -futures-util = "0.3.15" -async-stream = "0.3.2" -futures = "0.3.15" +chrono = "0.4.23" +futures-util = "0.3.26" +async-stream = "0.3.4" +futures = "0.3.26" [dev-dependencies] flowy-test = { path = "../flowy-test" } flowy-document = { path = "../flowy-document", features = ["flowy_unit_test"]} derive_more = {version = "0.99", features = ["display"]} -tracing-subscriber = "0.2.0" -unicode-segmentation = "1.8" +tracing-subscriber = "0.2.25" +unicode-segmentation = "1.10" color-eyre = { version = "0.5", default-features = false } criterion = "0.3" diff --git a/frontend/rust-lib/flowy-error/Cargo.toml b/frontend/rust-lib/flowy-error/Cargo.toml index f22566fcc3..8b53aead41 100644 --- a/frontend/rust-lib/flowy-error/Cargo.toml +++ b/frontend/rust-lib/flowy-error/Cargo.toml @@ -7,8 +7,8 @@ edition = "2018" [dependencies] flowy-derive = { path = "../flowy-derive" } -protobuf = {version = "2.20.0"} -bytes = "1.0" +protobuf = {version = "2.28.0"} +bytes = "1.4" anyhow = "1.0" thiserror = "1.0" @@ -20,7 +20,7 @@ flowy-client-ws = { path = "../../../shared-lib/flowy-client-ws", optional = tru serde_json = {version = "1.0", optional = true} serde_repr = { version = "0.1" } serde = "1.0" -reqwest = { version = "0.11", optional = true } +reqwest = { version = "0.11.14", optional = true } http-error-code = { git = "https://github.com/AppFlowy-IO/AppFlowy-Server", branch = "refactor/appflowy_server", optional = true } flowy-sqlite = { path = "../flowy-sqlite", optional = true} r2d2 = { version = "0.8", optional = true} diff --git a/frontend/rust-lib/flowy-folder/Cargo.toml b/frontend/rust-lib/flowy-folder/Cargo.toml index 241c732e7f..dc091b76c6 100644 --- a/frontend/rust-lib/flowy-folder/Cargo.toml +++ b/frontend/rust-lib/flowy-folder/Cargo.toml @@ -23,20 +23,20 @@ flowy-revision = { path = "../flowy-revision" } flowy-revision-persistence = { path = "../flowy-revision-persistence" } parking_lot = "0.12.1" -protobuf = {version = "2.18.0"} -log = "0.4.14" +protobuf = {version = "2.28.0"} +log = "0.4.17" diesel = {version = "1.4.8", features = ["sqlite"]} diesel_derives = {version = "1.4.1", features = ["sqlite"]} -futures = "0.3.15" +futures = "0.3.26" pin-project = "1.0" strum = "0.21" strum_macros = "0.21" -tokio = { version = "1", features = ["rt"] } +tokio = { version = "1.26", features = ["rt"] } lazy_static = "1.4.0" serde = { version = "1.0", features = ["derive"] } tracing = { version = "0.1", features = ["log"] } -bytes = { version = "1.0" } -unicode-segmentation = "1.8" +bytes = { version = "1.4" } +unicode-segmentation = "1.10" serde_json = "1.0" [dev-dependencies] diff --git a/frontend/rust-lib/flowy-net/Cargo.toml b/frontend/rust-lib/flowy-net/Cargo.toml index fb3e201b80..addea337b0 100644 --- a/frontend/rust-lib/flowy-net/Cargo.toml +++ b/frontend/rust-lib/flowy-net/Cargo.toml @@ -24,24 +24,24 @@ flowy-user = { path = "../flowy-user" } flowy-document = { path = "../flowy-document" } lazy_static = "1.4.0" lib-infra = { path = "../../../shared-lib/lib-infra" } -protobuf = {version = "2.18.0"} +protobuf = {version = "2.28.0"} lib-ws = { path = "../../../shared-lib/lib-ws" } -bytes = { version = "1.0" } +bytes = { version = "1.4" } anyhow = "1.0" -tokio = {version = "1", features = ["sync"]} +tokio = { version = "1.26", features = ["sync"]} parking_lot = "0.12.1" strum = "0.21" strum_macros = "0.21" tracing = { version = "0.1", features = ["log"] } dashmap = "5" -async-stream = "0.3.2" -futures-util = "0.3.15" -reqwest = "0.11" +async-stream = "0.3.4" +futures-util = "0.3.26" +reqwest = "0.11.14" hyper = "0.14" config = { version = "0.10.1", default-features = false, features = ["yaml"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -serde-aux = "1.0.1" +serde-aux = "1.1.0" nanoid = "0.4.0" thiserror = "1.0" diff --git a/frontend/rust-lib/flowy-notification/Cargo.toml b/frontend/rust-lib/flowy-notification/Cargo.toml index afbce15cd3..a7c88fd92b 100644 --- a/frontend/rust-lib/flowy-notification/Cargo.toml +++ b/frontend/rust-lib/flowy-notification/Cargo.toml @@ -7,9 +7,9 @@ edition = "2018" [dependencies] lazy_static = { version = "1.4.0" } -protobuf = { version = "2.20.0" } +protobuf = { version = "2.28.0" } tracing = { version = "0.1", features = ["log"] } -bytes = { version = "1.0" } +bytes = { version = "1.4" } serde = "1.0" flowy-derive = { path = "../flowy-derive" } diff --git a/frontend/rust-lib/flowy-revision/Cargo.toml b/frontend/rust-lib/flowy-revision/Cargo.toml index 68459b069d..7eb844e338 100644 --- a/frontend/rust-lib/flowy-revision/Cargo.toml +++ b/frontend/rust-lib/flowy-revision/Cargo.toml @@ -13,15 +13,15 @@ lib-infra = { path = "../../../shared-lib/lib-infra" } flowy-error = { path = "../flowy-error" } flowy-revision-persistence= { path = "../flowy-revision-persistence" } tracing = { version = "0.1", features = ["log"] } -tokio = {version = "1", features = ["sync"]} -bytes = { version = "1.1" } +tokio = { version = "1.26", features = ["sync"]} +bytes = { version = "1.4" } strum = "0.21" strum_macros = "0.21" dashmap = "5" serde = { version = "1.0", features = ["derive"] } -futures-util = "0.3.15" -futures = "0.3.15" -async-stream = "0.3.2" +futures-util = "0.3.26" +futures = "0.3.26" +async-stream = "0.3.4" serde_json = {version = "1.0"} [dev-dependencies] @@ -32,4 +32,4 @@ serde_json = { version = "1.0" } parking_lot = "0.12.1" [features] -flowy_unit_test = [] \ No newline at end of file +flowy_unit_test = [] diff --git a/frontend/rust-lib/flowy-sqlite/Cargo.toml b/frontend/rust-lib/flowy-sqlite/Cargo.toml index db366a3816..66ffe1795e 100644 --- a/frontend/rust-lib/flowy-sqlite/Cargo.toml +++ b/frontend/rust-lib/flowy-sqlite/Cargo.toml @@ -1,23 +1,23 @@ -[package] -name = "flowy-sqlite" -version = "0.1.0" -edition = "2018" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -diesel = { version = "1.4.8", features = ["sqlite"] } -diesel_derives = { version = "1.4.1", features = ["sqlite"] } -diesel_migrations = { version = "1.4.0", features = ["sqlite"] } -tracing = { version = "0.1", features = ["log"] } -lazy_static = "1.4.0" - -r2d2 = "0.8.9" -libsqlite3-sys = { version = ">=0.8.0, <0.24.0", features = ["bundled"] } -scheduled-thread-pool = "0.2.5" -error-chain = "=0.12.0" -openssl = { version = "0.10.38", optional = true, features = ["vendored"] } -openssl-sys = { version = "0.9.69", optional = true, features = ["vendored"] } - -[features] -openssl_vendored = ["openssl", "openssl-sys"] +[package] +name = "flowy-sqlite" +version = "0.1.0" +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +diesel = { version = "1.4.8", features = ["sqlite"] } +diesel_derives = { version = "1.4.1", features = ["sqlite"] } +diesel_migrations = { version = "1.4.0", features = ["sqlite"] } +tracing = { version = "0.1", features = ["log"] } +lazy_static = "1.4.0" + +r2d2 = "0.8.10" +libsqlite3-sys = { version = ">=0.8.0, <0.24.0", features = ["bundled"] } +scheduled-thread-pool = "0.2.6" +error-chain = "=0.12.0" +openssl = { version = "0.10.45", optional = true, features = ["vendored"] } +openssl-sys = { version = "0.9.80", optional = true, features = ["vendored"] } + +[features] +openssl_vendored = ["openssl", "openssl-sys"] diff --git a/frontend/rust-lib/flowy-task/Cargo.toml b/frontend/rust-lib/flowy-task/Cargo.toml index e8ef930f0a..ee3c749e26 100644 --- a/frontend/rust-lib/flowy-task/Cargo.toml +++ b/frontend/rust-lib/flowy-task/Cargo.toml @@ -7,11 +7,11 @@ edition = "2021" [dependencies] lib-infra = { path = "../../../shared-lib/lib-infra" } -tokio = {version = "1", features = ["sync", "macros", ]} -atomic_refcell = "0.1.8" +tokio = { version = "1.26", features = ["sync", "macros", ]} +atomic_refcell = "0.1.9" anyhow = "1.0" tracing = { version = "0.1", features = ["log"] } [dev-dependencies] rand = "0.8.5" -futures = "0.3.15" +futures = "0.3.26" diff --git a/frontend/rust-lib/flowy-test/Cargo.toml b/frontend/rust-lib/flowy-test/Cargo.toml index a381b41c2d..2e137f48c8 100644 --- a/frontend/rust-lib/flowy-test/Cargo.toml +++ b/frontend/rust-lib/flowy-test/Cargo.toml @@ -19,21 +19,21 @@ lib-infra = { path = "../../../shared-lib/lib-infra" } serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0"} -protobuf = {version = "2.24.1"} -claim = "0.5.0" -tokio = { version = "1", features = ["full"]} -futures-util = "0.3.15" +protobuf = {version = "2.28.0"} +#claim = "0.5.0" +tokio = { version = "1.26", features = ["full"]} +futures-util = "0.3.26" thread-id = "3.3.0" log = "0.4" -bytes = "1.0" +bytes = "1.4" nanoid = "0.4.0" [dev-dependencies] quickcheck = "1.0.3" quickcheck_macros = "0.9.1" -fake = "2.4.3" -futures = "0.3.15" +fake = "2.5.0" +futures = "0.3.26" serial_test = "0.5.1" [features] -dart = ["flowy-core/dart"] \ No newline at end of file +dart = ["flowy-core/dart"] diff --git a/frontend/rust-lib/flowy-user/Cargo.toml b/frontend/rust-lib/flowy-user/Cargo.toml index 2a2bced168..c87205d909 100644 --- a/frontend/rust-lib/flowy-user/Cargo.toml +++ b/frontend/rust-lib/flowy-user/Cargo.toml @@ -15,19 +15,19 @@ flowy-notification = { path = "../flowy-notification" } lib-dispatch = { path = "../lib-dispatch" } tracing = { version = "0.1", features = ["log"] } -bytes = "1.0" +bytes = "1.4" serde = { version = "1.0", features = ["derive"] } serde_json = {version = "1.0"} -log = "0.4.14" -protobuf = {version = "2.18.0"} +log = "0.4.17" +protobuf = {version = "2.28.0"} lazy_static = "1.4.0" diesel = {version = "1.4.8", features = ["sqlite"]} diesel_derives = {version = "1.4.1", features = ["sqlite"]} -once_cell = "1.7.2" +once_cell = "1.17.1" parking_lot = "0.12.1" strum = "0.21" strum_macros = "0.21" -tokio = { version = "1", features = ["rt"] } +tokio = { version = "1.26", features = ["rt"] } [dev-dependencies] flowy-test = { path = "../flowy-test" } diff --git a/frontend/rust-lib/lib-dispatch/Cargo.toml b/frontend/rust-lib/lib-dispatch/Cargo.toml index 1f6d9ece5a..e3411caf55 100644 --- a/frontend/rust-lib/lib-dispatch/Cargo.toml +++ b/frontend/rust-lib/lib-dispatch/Cargo.toml @@ -8,13 +8,13 @@ edition = "2018" [dependencies] pin-project = "1.0" futures-core = { version = "0.3", default-features = false } -futures-channel = "0.3.15" -futures = "0.3.15" -futures-util = "0.3.15" -bytes = {version = "1.0", features = ["serde"]} -tokio = { version = "1", features = ["full"] } +futures-channel = "0.3.26" +futures = "0.3.26" +futures-util = "0.3.26" +bytes = {version = "1.4", features = ["serde"]} +tokio = { version = "1.26", features = ["full"] } nanoid = "0.4.0" -log = "0.4.14" +log = "0.4.17" thread-id = "3.3.0" dyn-clone = "1.0" derivative = "2.2.0" @@ -24,12 +24,12 @@ serde_repr = { version = "0.1", optional = true } #optional crate bincode = { version = "1.3", optional = true} -protobuf = {version = "2.24.1", optional = true} +protobuf = {version = "2.28.0", optional = true} tracing = { version = "0.1"} [dev-dependencies] -tokio = { version = "1", features = ["full"] } -futures-util = "0.3.15" +tokio = { version = "1.26", features = ["full"] } +futures-util = "0.3.26" [features] default = ["use_protobuf"] diff --git a/frontend/rust-lib/lib-log/Cargo.toml b/frontend/rust-lib/lib-log/Cargo.toml index 193c3ea377..a02dcbed73 100644 --- a/frontend/rust-lib/lib-log/Cargo.toml +++ b/frontend/rust-lib/lib-log/Cargo.toml @@ -7,17 +7,17 @@ edition = "2018" [dependencies] -tracing-log = { version = "0.1.1"} -tracing-subscriber = { version = "0.2.12", features = ["registry", "env-filter", "ansi", "json"] } -tracing-bunyan-formatter = "0.2.2" +tracing-log = { version = "0.1.3"} +tracing-subscriber = { version = "0.2.25", features = ["registry", "env-filter", "ansi", "json"] } +tracing-bunyan-formatter = "0.2.6" tracing-appender = "0.1" tracing-core = "0.1" tracing = { version = "0.1", features = ["log"] } -log = "0.4.14" +log = "0.4.17" serde_json = "1.0" serde = "1.0" chrono = "0.4" lazy_static = "1.4.0" [features] -use_bunyan = [] \ No newline at end of file +use_bunyan = [] diff --git a/shared-lib/database-model/Cargo.toml b/shared-lib/database-model/Cargo.toml index 2f620eb71c..55ee6a5527 100644 --- a/shared-lib/database-model/Cargo.toml +++ b/shared-lib/database-model/Cargo.toml @@ -6,9 +6,9 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bytes = "1.0" +bytes = "1.4" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = {version = "1.0"} serde_repr = "0.1" nanoid = "0.4.0" -indexmap = {version = "1.9.1", features = ["serde"]} +indexmap = {version = "1.9.2", features = ["serde"]} diff --git a/shared-lib/flowy-client-network-config/Cargo.toml b/shared-lib/flowy-client-network-config/Cargo.toml index e35e03dcab..3913275b5c 100644 --- a/shared-lib/flowy-client-network-config/Cargo.toml +++ b/shared-lib/flowy-client-network-config/Cargo.toml @@ -9,4 +9,4 @@ edition = "2021" config = { version = "0.10.1", default-features = false, features = ["yaml"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -serde-aux = "1.0.1" +serde-aux = "1.1.0" diff --git a/shared-lib/flowy-client-ws/Cargo.toml b/shared-lib/flowy-client-ws/Cargo.toml index 62c45b09c1..088e061991 100644 --- a/shared-lib/flowy-client-ws/Cargo.toml +++ b/shared-lib/flowy-client-ws/Cargo.toml @@ -8,8 +8,8 @@ edition = "2021" [dependencies] lib-ws = { path = "../lib-ws" } lib-infra = { path = "../lib-infra" } -futures-util = "0.3.15" -tokio = {version = "1", features = ["sync"]} +futures-util = "0.3.26" +tokio = { version = "1.26", features = ["sync"]} parking_lot = "0.12.1" tracing = { version = "0.1", features = ["log"] } thiserror = "1.0" diff --git a/shared-lib/flowy-server-sync/Cargo.toml b/shared-lib/flowy-server-sync/Cargo.toml index e9ba2fb9d3..123e452fc0 100644 --- a/shared-lib/flowy-server-sync/Cargo.toml +++ b/shared-lib/flowy-server-sync/Cargo.toml @@ -11,13 +11,13 @@ ws-model = { path = "../ws-model" } document-model = { path = "../document-model" } folder-model = { path = "../folder-model" } flowy-sync = { path = "../flowy-sync" } -bytes = "1.0" -log = "0.4.14" -tokio = { version = "1", features = ["full"] } +bytes = "1.4" +log = "0.4.17" +tokio = { version = "1.26", features = ["full"] } serde = { version = "1.0", features = ["derive", "rc"] } lib-ot = { path = "../lib-ot" } lib-infra = { path = "../lib-infra" } dashmap = "5" -futures = "0.3.15" -async-stream = "0.3.2" +futures = "0.3.26" +async-stream = "0.3.4" tracing = { version = "0.1", features = ["log"] } diff --git a/shared-lib/flowy-sync/Cargo.toml b/shared-lib/flowy-sync/Cargo.toml index 876c51dcb7..a7fdbcb12a 100644 --- a/shared-lib/flowy-sync/Cargo.toml +++ b/shared-lib/flowy-sync/Cargo.toml @@ -15,6 +15,6 @@ document-model = { path = "../document-model" } strum = "0.21" strum_macros = "0.21" parking_lot = "0.12.1" -tokio = { version = "1", features = ["full"] } +tokio = { version = "1.26", features = ["full"] } serde = { version = "1.0", features = ["derive", "rc"] } tracing = { version = "0.1", features = ["log"] } diff --git a/shared-lib/lib-infra/Cargo.toml b/shared-lib/lib-infra/Cargo.toml index 2070ac9c41..d4d3196064 100644 --- a/shared-lib/lib-infra/Cargo.toml +++ b/shared-lib/lib-infra/Cargo.toml @@ -6,11 +6,11 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -chrono = "0.4.19" -bytes = { version = "1.0" } +chrono = "0.4.23" +bytes = { version = "1.4" } pin-project = "1.0.12" futures-core = { version = "0.3" } -tokio = { version = "1", features = ["time", "rt"] } +tokio = { version = "1.26", features = ["time", "rt"] } rand = "0.8.5" -async-trait = "0.1.59" +async-trait = "0.1.64" md5 = "0.7.0" diff --git a/shared-lib/lib-ot/Cargo.toml b/shared-lib/lib-ot/Cargo.toml index 1c8a7ced5e..259cf1bdd5 100644 --- a/shared-lib/lib-ot/Cargo.toml +++ b/shared-lib/lib-ot/Cargo.toml @@ -9,14 +9,14 @@ edition = "2018" serde = { version = "1.0", features = ["derive", "rc"] } thiserror = "1.0" serde_json = { version = "1.0" } -indexmap = {version = "1.9.1", features = ["serde"]} +indexmap = {version = "1.9.2", features = ["serde"]} log = "0.4" tracing = { version = "0.1", features = ["log"] } lazy_static = "1.4.0" strum = "0.21" strum_macros = "0.21" -bytes = "1.0" -indextree = "4.4.0" +bytes = "1.4" +indextree = "4.5.0" [features] diff --git a/shared-lib/lib-ws/Cargo.toml b/shared-lib/lib-ws/Cargo.toml index 602b0da62a..0191ea4fa5 100644 --- a/shared-lib/lib-ws/Cargo.toml +++ b/shared-lib/lib-ws/Cargo.toml @@ -12,21 +12,21 @@ serde_json = {version = "1.0"} lib-infra = { path = "../lib-infra" } tokio-tungstenite = "0.15" -futures-util = "0.3.17" -futures-channel = "0.3.17" -tokio = {version = "1", features = ["full"]} -futures = "0.3.17" -bytes = "1.0" +futures-util = "0.3.26" +futures-channel = "0.3.26" +tokio = { version = "1.26", features = ["full"]} +futures = "0.3.26" +bytes = "1.4" pin-project = "1.0" futures-core = { version = "0.3", default-features = false } -url = "2.2.2" +url = "2.3.1" log = "0.4" tracing = { version = "0.1", features = ["log"] } -protobuf = {version = "2.18.0"} +protobuf = {version = "2.28.0"} strum_macros = "0.21" parking_lot = "0.12.1" dashmap = "5" [dev-dependencies] -tokio = {version = "1", features = ["full"]} -env_logger = "0.8.2" \ No newline at end of file +tokio = { version = "1.26", features = ["full"]} +env_logger = "0.8.4" diff --git a/shared-lib/revision-model/Cargo.toml b/shared-lib/revision-model/Cargo.toml index 37b4a9a32a..6efc018b80 100644 --- a/shared-lib/revision-model/Cargo.toml +++ b/shared-lib/revision-model/Cargo.toml @@ -9,4 +9,4 @@ edition = "2021" serde = { version = "1.0" } serde_json = { version = "1.0" } md5 = "0.7.0" -bytes = "1.0" +bytes = "1.4" diff --git a/shared-lib/user-model/Cargo.toml b/shared-lib/user-model/Cargo.toml index dfc3b41466..70ed444a82 100644 --- a/shared-lib/user-model/Cargo.toml +++ b/shared-lib/user-model/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" [dependencies] serde = { version = "1.0" } validator = "0.16.0" -unicode-segmentation = "1.8" +unicode-segmentation = "1.10" fancy-regex = "0.11.0" lazy_static = "1.4.0" tracing = { version = "0.1", features = ["log"] } @@ -19,9 +19,9 @@ serde_repr = "0.1" nanoid = "0.4.0" quickcheck = "1.0.3" quickcheck_macros = "0.9.1" -fake = "2.4.3" -claim = "0.4.0" -futures = "0.3.15" +fake = "2.5.0" +#claim = "0.5.0" +futures = "0.3.26" serial_test = "0.5.1" -rand_core = "0.6.3" -rand = "0.8.5" \ No newline at end of file +rand_core = "0.6.4" +rand = "0.8.5" diff --git a/shared-lib/ws-model/Cargo.toml b/shared-lib/ws-model/Cargo.toml index 7e854c4456..0766be02ce 100644 --- a/shared-lib/ws-model/Cargo.toml +++ b/shared-lib/ws-model/Cargo.toml @@ -10,4 +10,4 @@ serde = { version = "1.0" } serde_json = { version = "1.0" } serde_repr = "0.1" revision-model = { path = "../revision-model"} -bytes = "1.0" +bytes = "1.4" From 24bf1c1893ae495f01d0d18f2fb09286871e5851 Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 3 Mar 2023 10:05:19 +0800 Subject: [PATCH 011/117] chore: config tokio runtime subscriber --- frontend/rust-lib/flowy-core/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index 70cf58fb5f..b6b0c4ad3a 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -122,7 +122,7 @@ pub struct AppFlowyCore { impl AppFlowyCore { pub fn new(config: AppFlowyCoreConfig) -> Self { - // console_subscriber::init(); + console_subscriber::init(); init_log(&config); init_kv(&config.storage_path); From 47ccfbf4edb767dff87587ac00047bd3956bd460 Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 3 Mar 2023 11:22:06 +0800 Subject: [PATCH 012/117] chore: add profiling feature --- frontend/rust-lib/.cargo/config.toml | 24 - frontend/rust-lib/dart-ffi/.cargo/config.toml | 2 + frontend/rust-lib/dart-ffi/Cargo.toml | 2 +- frontend/rust-lib/flowy-core/Cargo.toml | 5 +- frontend/rust-lib/flowy-core/src/lib.rs | 6 + .../services/database_view/editor_manager.rs | 25 +- shared-lib/Cargo.lock | 472 +++++++++++++----- .../user-model/src/parser/user_email.rs | 7 +- shared-lib/user-model/src/parser/user_name.rs | 13 +- 9 files changed, 389 insertions(+), 167 deletions(-) delete mode 100644 frontend/rust-lib/.cargo/config.toml create mode 100644 frontend/rust-lib/dart-ffi/.cargo/config.toml diff --git a/frontend/rust-lib/.cargo/config.toml b/frontend/rust-lib/.cargo/config.toml deleted file mode 100644 index f6792d6cbd..0000000000 --- a/frontend/rust-lib/.cargo/config.toml +++ /dev/null @@ -1,24 +0,0 @@ -[build] -rustflags = ["--cfg", "tokio_unstable"] - -[target.x86_64-apple-darwin] -rustflags=["-C", "link-arg=-mmacosx-version-min=10.11"] - -[target.aarch64-apple-darwin] -rustflags=["-C", "link-arg=-mmacosx-version-min=10.11"] - -[target.aarch64-linux-android] -ar = "path-to-ndk/llvm-ar" -linker = "path-to-ndk/aarch64-linux-android29-clang" - -[target.armv7-linux-androideabi] -ar = "path-to-ndk/llvm-ar" -linker = "path-to-ndk/armv7a-linux-androideabi29-clang" - -[target.i686-linux-android] -ar = "path-to-ndk/llvm-ar" -linker = "path-to-ndk/i686-linux-android29-clang" - -[target.x86_64-linux-android] -ar = "path-to-ndk/llvm-ar" -linker = "path-to-ndk/x86_64-linux-android29-clang" \ No newline at end of file diff --git a/frontend/rust-lib/dart-ffi/.cargo/config.toml b/frontend/rust-lib/dart-ffi/.cargo/config.toml new file mode 100644 index 0000000000..bff29e6e17 --- /dev/null +++ b/frontend/rust-lib/dart-ffi/.cargo/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["--cfg", "tokio_unstable"] diff --git a/frontend/rust-lib/dart-ffi/Cargo.toml b/frontend/rust-lib/dart-ffi/Cargo.toml index 7f7a2af45f..66a919987b 100644 --- a/frontend/rust-lib/dart-ffi/Cargo.toml +++ b/frontend/rust-lib/dart-ffi/Cargo.toml @@ -15,7 +15,7 @@ crate-type = ["staticlib"] allo-isolate = { version = "^0.1", features = ["catch-unwind"] } byteorder = { version = "1.4.3" } protobuf = { version = "2.28.0" } -tokio = { version = "1.26", features = ["rt", "rt-multi-thread"] } +tokio = { version = "1.26", features = ["full", "rt-multi-thread", "tracing"] } log = "0.4.17" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0" } diff --git a/frontend/rust-lib/flowy-core/Cargo.toml b/frontend/rust-lib/flowy-core/Cargo.toml index c36c635fe3..591f459963 100644 --- a/frontend/rust-lib/flowy-core/Cargo.toml +++ b/frontend/rust-lib/flowy-core/Cargo.toml @@ -24,8 +24,8 @@ flowy-task = { path = "../flowy-task" } tracing = { version = "0.1", features = ["log"] } futures-core = { version = "0.3", default-features = false } bytes = "1.4" -tokio = { version = "1.26", features = ["full", "tracing"] } -console-subscriber = "0.1.8" +tokio = { version = "1.26", features = ["full"] } +console-subscriber = { version = "0.1.8", optional = true } parking_lot = "0.12.1" revision-model = { path = "../../../shared-lib/revision-model" } @@ -37,6 +37,7 @@ serde_json = "1.0" [features] default = ["rev-sqlite"] +profiling = ["console-subscriber", "tokio/tracing"] http_sync = ["flowy-folder/cloud_sync", "flowy-document/cloud_sync"] native_sync = ["flowy-folder/cloud_sync", "flowy-document/cloud_sync"] use_bunyan = ["lib-log/use_bunyan"] diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index b6b0c4ad3a..d096c65e60 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -102,6 +102,11 @@ fn create_log_filter(level: String, with_crates: Vec) -> String { filters.push(format!("dart_ffi={}", "info")); filters.push(format!("flowy_sqlite={}", "info")); filters.push(format!("flowy_net={}", "info")); + #[cfg(feature = "profiling")] + filters.push(format!("tokio={}", level)); + + #[cfg(feature = "profiling")] + filters.push(format!("runtime={}", level)); filters.push(format!("tokio=trace,runtime=trace")); filters.join(",") } @@ -122,6 +127,7 @@ pub struct AppFlowyCore { impl AppFlowyCore { pub fn new(config: AppFlowyCoreConfig) -> Self { + #[cfg(feature = "profiling")] console_subscriber::init(); init_log(&config); diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs index 70881b4593..3d68613a4e 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs @@ -352,17 +352,20 @@ fn listen_on_database_block_event( ) { tokio::spawn(async move { loop { - while let Ok(event) = block_event_rx.recv().await { - let read_guard = view_editors.read().await; - let view_editors = read_guard.values(); - let event = if view_editors.len() == 1 { - Cow::Owned(event) - } else { - Cow::Borrowed(&event) - }; - for view_editor in view_editors { - view_editor.handle_block_event(event.clone()).await; - } + match block_event_rx.recv().await { + Ok(event) => { + let read_guard = view_editors.read().await; + let view_editors = read_guard.values(); + let event = if view_editors.len() == 1 { + Cow::Owned(event) + } else { + Cow::Borrowed(&event) + }; + for view_editor in view_editors { + view_editor.handle_block_event(event.clone()).await; + } + }, + Err(_) => break, } } }); diff --git a/shared-lib/Cargo.lock b/shared-lib/Cargo.lock index d9cfacea20..7437eb1e5f 100644 --- a/shared-lib/Cargo.lock +++ b/shared-lib/Cargo.lock @@ -11,6 +11,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "arrayvec" version = "0.5.2" @@ -19,19 +28,20 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "async-stream" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e" +checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" dependencies = [ "async-stream-impl", "futures-core", + "pin-project-lite", ] [[package]] name = "async-stream-impl" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" +checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" dependencies = [ "proc-macro2", "quote", @@ -40,9 +50,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.59" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -62,9 +72,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" @@ -102,6 +112,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "bumpalo" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" + [[package]] name = "byteorder" version = "1.4.3" @@ -110,9 +126,15 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -122,24 +144,27 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "time", + "wasm-bindgen", "winapi", ] [[package]] -name = "claim" -version = "0.4.0" +name = "codespan-reporting" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ad37958d55b29a7088909368968d2fe876a24c203f8441195130f3b15194b9" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" dependencies = [ - "autocfg", + "termcolor", + "unicode-width", ] [[package]] @@ -154,6 +179,12 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + [[package]] name = "cpufeatures" version = "0.2.1" @@ -163,6 +194,50 @@ dependencies = [ "libc", ] +[[package]] +name = "cxx" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dashmap" version = "5.2.0" @@ -318,19 +393,18 @@ dependencies = [ [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "futures" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -343,9 +417,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -353,15 +427,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -370,18 +444,16 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ - "autocfg", - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -389,23 +461,22 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.17" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ - "autocfg", "futures-channel", "futures-core", "futures-io", @@ -415,8 +486,6 @@ dependencies = [ "memchr", "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] @@ -438,7 +507,7 @@ checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.10.0+wasi-snapshot-preview1", ] [[package]] @@ -488,6 +557,30 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "iana-time-zone" +version = "0.1.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "winapi", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "idna" version = "0.2.3" @@ -500,10 +593,20 @@ dependencies = [ ] [[package]] -name = "indexmap" -version = "1.9.1" +name = "idna" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -512,9 +615,9 @@ dependencies = [ [[package]] name = "indextree" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b4b46b3311ebd8e5cd44f6b03b36e0f48a70552cf6b036afcebc5626794066" +checksum = "497f036ac2fae75c34224648a77802e5dd4e9cfb56f4713ab6b12b7160a0523b" [[package]] name = "instant" @@ -531,6 +634,15 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "js-sys" +version = "0.3.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -609,9 +721,18 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.107" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "link-cplusplus" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" +dependencies = [ + "cc", +] [[package]] name = "linked-hash-map" @@ -630,9 +751,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -657,24 +778,14 @@ checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "mio" -version = "0.7.14" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", - "miow", - "ntapi", - "winapi", -] - -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.45.0", ] [[package]] @@ -697,15 +808,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi", -] - [[package]] name = "num-integer" version = "0.1.44" @@ -737,9 +839,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "opaque-debug" @@ -792,14 +894,14 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pin-project" @@ -839,18 +941,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" version = "1.0.47" @@ -862,9 +952,9 @@ dependencies = [ [[package]] name = "protobuf" -version = "2.25.2" +version = "2.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c327e191621a2158159df97cdbc2e7074bb4e940275e35abf38eb3d2595754" +checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94" [[package]] name = "quickcheck" @@ -920,9 +1010,9 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] @@ -975,6 +1065,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" + [[package]] name = "serde" version = "1.0.136" @@ -1084,6 +1180,16 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +[[package]] +name = "socket2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -1155,7 +1261,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", - "wasi", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] @@ -1176,9 +1282,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.14.0" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" dependencies = [ "autocfg", "bytes", @@ -1186,19 +1292,19 @@ dependencies = [ "memchr", "mio", "num_cpus", - "once_cell", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", + "socket2", "tokio-macros", - "winapi", + "windows-sys 0.45.0", ] [[package]] name = "tokio-macros" -version = "1.6.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ "proc-macro2", "quote", @@ -1299,19 +1405,24 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", - "idna", - "matches", + "idna 0.3.0", "percent-encoding", ] @@ -1319,7 +1430,6 @@ dependencies = [ name = "user-model" version = "0.1.0" dependencies = [ - "claim", "fake", "fancy-regex", "futures", @@ -1350,7 +1460,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32ad5bf234c7d3ad1042e5252b7eddb2c4669ee23f32c7dd0e9b7705f07ef591" dependencies = [ - "idna", + "idna 0.2.3", "lazy_static", "regex", "serde", @@ -1371,6 +1481,66 @@ version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" + [[package]] name = "winapi" version = "0.3.9" @@ -1408,43 +1578,109 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows_aarch64_msvc 0.36.1", + "windows_i686_gnu 0.36.1", + "windows_i686_msvc 0.36.1", + "windows_x86_64_gnu 0.36.1", + "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + [[package]] name = "windows_aarch64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + [[package]] name = "windows_i686_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + [[package]] name = "windows_i686_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + [[package]] name = "windows_x86_64_gnu" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + [[package]] name = "windows_x86_64_msvc" version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + [[package]] name = "ws-model" version = "0.1.0" diff --git a/shared-lib/user-model/src/parser/user_email.rs b/shared-lib/user-model/src/parser/user_email.rs index d8b0ca942d..176fd0f34b 100644 --- a/shared-lib/user-model/src/parser/user_email.rs +++ b/shared-lib/user-model/src/parser/user_email.rs @@ -27,7 +27,6 @@ impl AsRef for UserEmail { #[cfg(test)] mod tests { use super::*; - use claim::assert_err; use fake::{faker::internet::en::SafeEmail, Fake}; use rand::prelude::StdRng; use rand_core::SeedableRng; @@ -35,19 +34,19 @@ mod tests { #[test] fn empty_string_is_rejected() { let email = "".to_string(); - assert_err!(UserEmail::parse(email)); + assert!(UserEmail::parse(email).is_err()); } #[test] fn email_missing_at_symbol_is_rejected() { let email = "helloworld.com".to_string(); - assert_err!(UserEmail::parse(email)); + assert!(UserEmail::parse(email).is_err()); } #[test] fn email_missing_subject_is_rejected() { let email = "@domain.com".to_string(); - assert_err!(UserEmail::parse(email)); + assert!(UserEmail::parse(email).is_err()); } #[derive(Debug, Clone)] diff --git a/shared-lib/user-model/src/parser/user_name.rs b/shared-lib/user-model/src/parser/user_name.rs index 0e04b54136..4a8d8b0856 100644 --- a/shared-lib/user-model/src/parser/user_name.rs +++ b/shared-lib/user-model/src/parser/user_name.rs @@ -42,43 +42,42 @@ impl AsRef for UserName { #[cfg(test)] mod tests { use super::UserName; - use claim::{assert_err, assert_ok}; #[test] fn a_256_grapheme_long_name_is_valid() { let name = "a̐".repeat(256); - assert_ok!(UserName::parse(name)); + assert!(UserName::parse(name).is_ok()); } #[test] fn a_name_longer_than_256_graphemes_is_rejected() { let name = "a".repeat(257); - assert_err!(UserName::parse(name)); + assert!(UserName::parse(name).is_err()); } #[test] fn whitespace_only_names_are_rejected() { let name = " ".to_string(); - assert_err!(UserName::parse(name)); + assert!(UserName::parse(name).is_err()); } #[test] fn empty_string_is_rejected() { let name = "".to_string(); - assert_err!(UserName::parse(name)); + assert!(UserName::parse(name).is_err()); } #[test] fn names_containing_an_invalid_character_are_rejected() { for name in &['/', '(', ')', '"', '<', '>', '\\', '{', '}'] { let name = name.to_string(); - assert_err!(UserName::parse(name)); + assert!(UserName::parse(name).is_err()); } } #[test] fn a_valid_name_is_parsed_successfully() { let name = "nathan".to_string(); - assert_ok!(UserName::parse(name)); + assert!(UserName::parse(name).is_ok()); } } From a2bdb08a845eee58d43c5796a85643178b9c491b Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 3 Mar 2023 17:58:45 +0800 Subject: [PATCH 013/117] chore: setup auto login --- frontend/appflowy_tauri/src-tauri/Cargo.lock | 291 +----------------- .../appflowy_tauri/src/appflowy_app/App.tsx | 2 + .../components/auth/GetStarted/GetStarted.tsx | 31 ++ .../components/auth/Login/Login.hooks.ts | 29 +- .../components/auth/ProtectedRoutes.tsx | 4 +- .../effects/database/database_controller.ts | 2 +- .../stores/reducers/current-user/slice.ts | 4 +- .../src/services/workspace/controller.rs | 3 - frontend/rust-lib/flowy-task/src/scheduler.rs | 1 - 9 files changed, 65 insertions(+), 302 deletions(-) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/auth/GetStarted/GetStarted.tsx diff --git a/frontend/appflowy_tauri/src-tauri/Cargo.lock b/frontend/appflowy_tauri/src-tauri/Cargo.lock index 85ab5aa964..406589203c 100644 --- a/frontend/appflowy_tauri/src-tauri/Cargo.lock +++ b/frontend/appflowy_tauri/src-tauri/Cargo.lock @@ -173,52 +173,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "axum" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fb79c228270dcf2426e74864cabc94babb5dbab01a4314e702d2f16540e1591" -dependencies = [ - "async-trait", - "axum-core", - "bitflags", - "bytes", - "futures-util", - "http", - "http-body", - "hyper", - "itoa 1.0.5", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "sync_wrapper", - "tower", - "tower-http", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-core" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http", - "http-body", - "mime", - "rustversion", - "tower-layer", - "tower-service", -] - [[package]] name = "backtrace" version = "0.3.67" @@ -630,7 +584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b076e143e1d9538dde65da30f8481c2a6c44040edb8e02b9bf1351edb92ce3" dependencies = [ "lazy_static", - "nom 5.1.2", + "nom", "serde", "yaml-rust", ] @@ -650,42 +604,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "console-api" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e57ff02e8ad8e06ab9731d5dc72dc23bef9200778eae1a89d555d8c42e5d4a86" -dependencies = [ - "prost", - "prost-types", - "tonic", - "tracing-core", -] - -[[package]] -name = "console-subscriber" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a3a81dfaf6b66bce5d159eddae701e3a002f194d378cbf7be5f053c281d9be" -dependencies = [ - "console-api", - "crossbeam-channel", - "crossbeam-utils", - "futures", - "hdrhistogram", - "humantime", - "prost-types", - "serde", - "serde_json", - "thread_local", - "tokio", - "tokio-stream", - "tonic", - "tracing", - "tracing-core", - "tracing-subscriber 0.3.16", -] - [[package]] name = "convert_case" version = "0.4.0" @@ -1297,7 +1215,6 @@ name = "flowy-core" version = "0.1.0" dependencies = [ "bytes", - "console-subscriber", "database-model", "flowy-client-ws", "flowy-database", @@ -2148,19 +2065,6 @@ dependencies = [ "ahash", ] -[[package]] -name = "hdrhistogram" -version = "7.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8" -dependencies = [ - "base64 0.13.1", - "byteorder", - "flate2", - "nom 7.1.3", - "num-traits", -] - [[package]] name = "heck" version = "0.3.3" @@ -2237,12 +2141,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" -[[package]] -name = "http-range-header" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29" - [[package]] name = "httparse" version = "1.8.0" @@ -2261,12 +2159,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02296996cb8796d7c6e3bc2d9211b7802812d36999a51bb754123ead7d37d026" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.23" @@ -2291,18 +2183,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-timeout" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" -dependencies = [ - "hyper", - "pin-project-lite", - "tokio", - "tokio-io-timeout", -] - [[package]] name = "hyper-tls" version = "0.5.0" @@ -2788,12 +2668,6 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" -[[package]] -name = "matchit" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" - [[package]] name = "md5" version = "0.7.0" @@ -2851,12 +2725,6 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.6.2" @@ -2956,16 +2824,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -3548,38 +3406,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prost" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-derive" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "prost-types" -version = "0.11.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88" -dependencies = [ - "prost", -] - [[package]] name = "protobuf" version = "2.28.0" @@ -4479,12 +4305,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "system-deps" version = "5.0.0" @@ -4921,20 +4741,9 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "tracing", "windows-sys 0.45.0", ] -[[package]] -name = "tokio-io-timeout" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" -dependencies = [ - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-macros" version = "1.8.2" @@ -4956,17 +4765,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-stream" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - [[package]] name = "tokio-tungstenite" version = "0.15.0" @@ -5003,83 +4801,6 @@ dependencies = [ "serde", ] -[[package]] -name = "tonic" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" -dependencies = [ - "async-stream", - "async-trait", - "axum", - "base64 0.13.1", - "bytes", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-timeout", - "percent-encoding", - "pin-project", - "prost", - "prost-derive", - "tokio", - "tokio-stream", - "tokio-util", - "tower", - "tower-layer", - "tower-service", - "tracing", - "tracing-futures", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "indexmap", - "pin-project", - "pin-project-lite", - "rand 0.8.5", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858" -dependencies = [ - "bitflags", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-range-header", - "pin-project-lite", - "tower", - "tower-layer", - "tower-service", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - [[package]] name = "tower-service" version = "0.3.2" @@ -5148,16 +4869,6 @@ dependencies = [ "valuable", ] -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - [[package]] name = "tracing-log" version = "0.1.3" diff --git a/frontend/appflowy_tauri/src/appflowy_app/App.tsx b/frontend/appflowy_tauri/src/appflowy_app/App.tsx index f586610cf0..38342048ab 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/App.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/App.tsx @@ -14,6 +14,7 @@ import { ConfirmAccountPage } from './views/ConfirmAccountPage'; import { ErrorHandlerPage } from './components/error/ErrorHandlerPage'; import initializeI18n from './stores/i18n/initializeI18n'; import { TestAPI } from './components/TestApiButton/TestAPI'; +import { GetStarted } from './components/auth/GetStarted/GetStarted'; initializeI18n(); @@ -31,6 +32,7 @@ const App = () => { } /> }> + }> }> }> diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/GetStarted/GetStarted.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/auth/GetStarted/GetStarted.tsx new file mode 100644 index 0000000000..04cd2865f1 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/auth/GetStarted/GetStarted.tsx @@ -0,0 +1,31 @@ +import { t } from 'i18next'; +import { AppflowyLogo } from '../../_shared/svg/AppflowyLogo'; +import { Button } from '../../_shared/Button'; +import { useLogin } from '../Login/Login.hooks'; + +export const GetStarted = () => { + const { onAutoSignInClick } = useLogin(); + return ( + <> +
e.preventDefault()} method='POST'> +
+
+ +
+ +
+ + {t('signIn.loginTitle').replace('@:appName', 'AppFlowy')} + +
+ +
+ +
+
+
+ + ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/Login/Login.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/auth/Login/Login.hooks.ts index 7557c9cf38..7d07a339b2 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/Login/Login.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/auth/Login/Login.hooks.ts @@ -3,6 +3,7 @@ import { currentUserActions } from '../../../stores/reducers/current-user/slice' import { useAppDispatch, useAppSelector } from '../../../stores/store'; import { useNavigate } from 'react-router-dom'; import { useAuth } from '../auth.hooks'; +import { nanoid } from 'nanoid'; export const useLogin = () => { const [email, setEmail] = useState(''); @@ -11,7 +12,7 @@ export const useLogin = () => { const appDispatch = useAppDispatch(); const currentUser = useAppSelector((state) => state.currentUser); const navigate = useNavigate(); - const { login } = useAuth(); + const { login, register } = useAuth(); const [authError, setAuthError] = useState(false); function onTogglePassword() { @@ -29,10 +30,31 @@ export const useLogin = () => { setPassword(v); } + async function onAutoSignInClick() { + try { + const fakeEmail = nanoid(8) + '@appflowy.io'; + const fakePassword = 'AppFlowy123@'; + const userProfile = await register(fakeEmail, fakePassword, 'Me'); + const { id, name, token } = userProfile; + appDispatch( + currentUserActions.updateUser({ + id: id, + displayName: name, + email: email, + token: token, + isAuthenticated: true, + }) + ); + navigate('/'); + } catch (e) { + setAuthError(true); + } + } + async function onSignInClick() { try { - const result = await login(email, password); - const { id, name, token } = result; + const userProfile = await login(email, password); + const { id, name, token } = userProfile; appDispatch( currentUserActions.updateUser({ id: id, @@ -52,6 +74,7 @@ export const useLogin = () => { showPassword, onTogglePassword, onSignInClick, + onAutoSignInClick, email, setEmail: _setEmail, password, diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/auth/ProtectedRoutes.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/auth/ProtectedRoutes.tsx index 0861ce9b33..4904194cb9 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/auth/ProtectedRoutes.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/auth/ProtectedRoutes.tsx @@ -1,6 +1,6 @@ import { Navigate, Outlet, useLocation } from 'react-router-dom'; import { useAuth } from './auth.hooks'; -import { Screen } from '../../components/layout/Screen'; +import { Screen } from '../layout/Screen'; export const ProtectedRoutes = () => { const location = useLocation(); @@ -11,6 +11,6 @@ export const ProtectedRoutes = () => { ) : ( - + ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts index 0ef8c27a1f..819818dae8 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts @@ -1,7 +1,7 @@ import { DatabaseBackendService } from './database_bd_svc'; import { FieldController, FieldInfo } from './field/field_controller'; import { DatabaseViewCache } from './view/database_view_cache'; -import { DatabasePB } from '../../../../services/backend/models/flowy-database/grid_entities'; +import { DatabasePB } from '../../../../services/backend'; import { RowChangedReason, RowInfo } from './row/row_cache'; import { Err, Ok } from 'ts-results'; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts index 190dfcfb9c..2e97d45cd9 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts @@ -8,7 +8,7 @@ export interface ICurrentUser { email?: string; token?: string; isAuthenticated: boolean; - workspaceSetting?: WorkspaceSettingPB, + workspaceSetting?: WorkspaceSettingPB; } const initialState: ICurrentUser | null = { @@ -16,7 +16,7 @@ const initialState: ICurrentUser | null = { displayName: 'Me 😃', email: `${nanoid(4)}@gmail.com`, token: nanoid(8), - isAuthenticated: true, + isAuthenticated: false, }; export const currentUserSlice = createSlice({ diff --git a/frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs b/frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs index 710a6bf8ae..ad704f2650 100644 --- a/frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/workspace/controller.rs @@ -179,7 +179,6 @@ impl WorkspaceController { } impl WorkspaceController { - #[tracing::instrument(level = "trace", skip(self), err)] async fn create_workspace_on_server( &self, params: CreateWorkspaceParams, @@ -188,7 +187,6 @@ impl WorkspaceController { self.cloud_service.create_workspace(&token, params).await } - #[tracing::instrument(level = "trace", skip(self), err)] fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), FlowyError> { let (token, server) = (self.user.token()?, self.cloud_service.clone()); tokio::spawn(async move { @@ -203,7 +201,6 @@ impl WorkspaceController { Ok(()) } - #[tracing::instrument(level = "trace", skip(self), err)] fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), FlowyError> { let params = WorkspaceIdPB { value: Some(workspace_id.to_string()), diff --git a/frontend/rust-lib/flowy-task/src/scheduler.rs b/frontend/rust-lib/flowy-task/src/scheduler.rs index 5e24114d3f..70d861a9cf 100644 --- a/frontend/rust-lib/flowy-task/src/scheduler.rs +++ b/frontend/rust-lib/flowy-task/src/scheduler.rs @@ -59,7 +59,6 @@ impl TaskDispatcher { self.store.clear(); } - #[tracing::instrument(level = "trace", skip_all)] pub(crate) async fn process_next_task(&mut self) -> Option<()> { let pending_task = self.queue.mut_head(|list| list.pop())?; let mut task = self.store.remove_task(&pending_task.id)?; From 24340f30910b0d03b92a712389be67bbbd33eb9f Mon Sep 17 00:00:00 2001 From: nathan Date: Fri, 3 Mar 2023 19:06:57 +0800 Subject: [PATCH 014/117] chore: fix tauri build --- .../effects/database/cell/cell_controller.ts | 14 ++++++---- .../effects/database/cell/data_parser.ts | 28 +++++++++---------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts index 6d3050d88a..853bc2f006 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts @@ -1,6 +1,5 @@ import { CellIdentifier } from './cell_bd_svc'; import { CellCache, CellCacheKey } from './cell_cache'; -import { FieldController } from '../field/field_controller'; import { CellDataLoader } from './data_parser'; import { CellDataPersistence } from './data_persistence'; import { FieldBackendService, TypeOptionParser } from '../field/field_bd_svc'; @@ -112,21 +111,24 @@ export class CellController { } class CellDataNotifier extends ChangeNotifier { - _cellData: T | null; + _cellData: Option; constructor(cellData: T) { super(); - this._cellData = cellData; + this._cellData = Some(cellData); } - set cellData(data: T | null) { + set cellData(data: Option) { if (this._cellData !== data) { this._cellData = data; - this.notify(this._cellData); + + if (this._cellData.some) { + this.notify(this._cellData.val); + } } } - get cellData(): T | null { + get cellData(): Option { return this._cellData; } } diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts index e44867c0df..20a7a3e68d 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts @@ -3,11 +3,11 @@ import { CellBackendService, CellIdentifier } from './cell_bd_svc'; import { DateCellDataPB } from '../../../../../services/backend/models/flowy-database/date_type_option_entities'; import { SelectOptionCellDataPB } from '../../../../../services/backend/models/flowy-database/select_type_option'; import { URLCellDataPB } from '../../../../../services/backend/models/flowy-database/url_type_option_entities'; -import { Err, Ok } from 'ts-results'; +import { Err, None, Ok, Option, Some } from 'ts-results'; import { Log } from '../../../../utils/log'; abstract class CellDataParser { - abstract parserData(data: Uint8Array): T; + abstract parserData(data: Uint8Array): Option; } class CellDataLoader { @@ -34,32 +34,32 @@ export const utf8Decoder = new TextDecoder('utf-8'); export const utf8Encoder = new TextEncoder(); class StringCellDataParser extends CellDataParser { - parserData(data: Uint8Array): string { - return utf8Decoder.decode(data); + parserData(data: Uint8Array): Option { + return Some(utf8Decoder.decode(data)); } } class DateCellDataParser extends CellDataParser { - parserData(data: Uint8Array): DateCellDataPB { - return DateCellDataPB.deserializeBinary(data); + parserData(data: Uint8Array): Option { + return Some(DateCellDataPB.deserializeBinary(data)); } } -class SelectOptionCellDataParser extends CellDataParser { - parserData(data: Uint8Array): SelectOptionCellDataPB | undefined { +class SelectOptionCellDataParser extends CellDataParser { + parserData(data: Uint8Array): Option { if (data.length === 0) { - return undefined; + return None; } - return SelectOptionCellDataPB.deserializeBinary(data); + return Some(SelectOptionCellDataPB.deserializeBinary(data)); } } -class URLCellDataParser extends CellDataParser { - parserData(data: Uint8Array): URLCellDataPB | undefined { +class URLCellDataParser extends CellDataParser { + parserData(data: Uint8Array): Option { if (data.length === 0) { - return undefined; + return None; } - return URLCellDataPB.deserializeBinary(data); + return Some(URLCellDataPB.deserializeBinary(data)); } } From 11649ef16dd20ce79f8344fe10fb78e749edf0d2 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Fri, 3 Mar 2023 17:14:58 +0600 Subject: [PATCH 015/117] chore: (unstable) using controllers --- .../components/TestApiButton/TestGrid.tsx | 14 +- .../_shared/database-hooks/loadField.ts | 99 ++++++++ .../_shared/database-hooks/useCell.ts | 40 +++ .../_shared/database-hooks/useDatabase.ts | 50 ++++ .../_shared/database-hooks/useRow.ts | 32 +++ .../components/board/Board.hooks.ts | 32 +-- .../appflowy_app/components/board/Board.tsx | 37 ++- .../components/board/BoardBlock.tsx | 32 +-- .../{BoardBlockItem.tsx => BoardCard.tsx} | 62 ++--- .../components/board/BoardCell.tsx | 23 ++ .../effects/database/database_controller.ts | 3 +- .../stores/reducers/board/slice.ts | 2 +- .../stores/reducers/database/slice.ts | 240 ++++-------------- .../src/appflowy_app/views/BoardPage.tsx | 10 +- 14 files changed, 401 insertions(+), 275 deletions(-) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts rename frontend/appflowy_tauri/src/appflowy_app/components/board/{BoardBlockItem.tsx => BoardCard.tsx} (67%) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCell.tsx diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx index d0ccbfab47..b75e42e841 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/TestApiButton/TestGrid.tsx @@ -5,7 +5,7 @@ import { SingleSelectTypeOptionPB, ViewLayoutTypePB, } from '../../../services/backend'; -import { Log } from '../../utils/log'; +import {Log} from '../../utils/log'; import { assertFieldName, assertNumberOfFields, @@ -20,10 +20,10 @@ import { SelectOptionBackendService, SelectOptionCellBackendService, } from '../../stores/effects/database/cell/select_option_bd_svc'; -import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller'; -import { None, Some } from 'ts-results'; -import { RowBackendService } from '../../stores/effects/database/row/row_bd_svc'; -import { makeSingleSelectTypeOptionContext } from '../../stores/effects/database/field/type_option/type_option_context'; +import {TypeOptionController} from '../../stores/effects/database/field/type_option/type_option_controller'; +import {None, Some} from 'ts-results'; +import {RowBackendService} from '../../stores/effects/database/row/row_bd_svc'; +import {makeSingleSelectTypeOptionContext} from '../../stores/effects/database/field/type_option/type_option_context'; export const TestCreateGrid = () => { async function createBuildInGrid() { @@ -180,6 +180,7 @@ export const TestEditField = () => { await controller.initialize(); const newName = 'hello world'; await controller.setFieldName(newName); + await controller.switchToField(FieldType.MultiSelect); await assertFieldName(view.id, firstFieldInfo.field.id, firstFieldInfo.field.field_type, newName); await databaseController.dispose(); @@ -199,6 +200,9 @@ export const TestCreateNewField = () => { const controller = new TypeOptionController(view.id, None); await controller.initialize(); await assertNumberOfFields(view.id, 4); + + + await databaseController.dispose(); } diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts new file mode 100644 index 0000000000..50a69d0828 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts @@ -0,0 +1,99 @@ +import { TypeOptionController } from '../../../stores/effects/database/field/type_option/type_option_controller'; +import { Some } from 'ts-results'; +import { IDatabaseField, ISelectOption } from '../../../stores/reducers/database/slice'; +import { + ChecklistTypeOptionPB, + DateFormat, + FieldType, + MultiSelectTypeOptionPB, + NumberFormat, + SingleSelectTypeOptionPB, + TimeFormat, +} from '../../../../services/backend'; +import { + makeChecklistTypeOptionContext, + makeDateTypeOptionContext, + makeMultiSelectTypeOptionContext, + makeNumberTypeOptionContext, + makeSingleSelectTypeOptionContext, +} from '../../../stores/effects/database/field/type_option/type_option_context'; +import { boardActions } from '../../../stores/reducers/board/slice'; +import { FieldInfo } from '../../../stores/effects/database/field/field_controller'; +import { AppDispatch } from '../../../stores/store'; + +export default async function (viewId: string, fieldInfo: FieldInfo, dispatch?: AppDispatch): Promise { + const field = fieldInfo.field; + const typeOptionController = new TypeOptionController(viewId, Some(fieldInfo)); + + let selectOptions: ISelectOption[] | undefined; + let numberFormat: NumberFormat | undefined; + let dateFormat: DateFormat | undefined; + let timeFormat: TimeFormat | undefined; + let includeTime: boolean | undefined; + + // temporary hack to set grouping field + let groupingFieldSelected = false; + + switch (field.field_type) { + case FieldType.SingleSelect: + case FieldType.MultiSelect: + case FieldType.Checklist: + { + let typeOption: SingleSelectTypeOptionPB | MultiSelectTypeOptionPB | ChecklistTypeOptionPB | undefined; + + if (field.field_type === FieldType.SingleSelect) { + typeOption = (await makeSingleSelectTypeOptionContext(typeOptionController).getTypeOption()).unwrap(); + if (!groupingFieldSelected) { + if (dispatch) { + dispatch(boardActions.setGroupingFieldId({ fieldId: field.id })); + } + groupingFieldSelected = true; + } + } + if (field.field_type === FieldType.MultiSelect) { + typeOption = (await makeMultiSelectTypeOptionContext(typeOptionController).getTypeOption()).unwrap(); + } + if (field.field_type === FieldType.Checklist) { + typeOption = (await makeChecklistTypeOptionContext(typeOptionController).getTypeOption()).unwrap(); + } + + if (typeOption) { + selectOptions = typeOption.options.map((option) => { + return { + selectOptionId: option.id, + title: option.name, + color: option.color, + }; + }); + } + } + break; + case FieldType.Number: + { + const typeOption = (await makeNumberTypeOptionContext(typeOptionController).getTypeOption()).unwrap(); + numberFormat = typeOption.format; + } + break; + case FieldType.DateTime: + { + const typeOption = (await makeDateTypeOptionContext(typeOptionController).getTypeOption()).unwrap(); + dateFormat = typeOption.date_format; + timeFormat = typeOption.time_format; + includeTime = typeOption.include_time; + } + break; + } + + return { + fieldId: field.id, + title: field.name, + fieldType: field.field_type, + fieldOptions: { + selectOptions, + numberFormat, + dateFormat, + timeFormat, + includeTime, + }, + }; +} diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts new file mode 100644 index 0000000000..0a270c86ef --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts @@ -0,0 +1,40 @@ +import { CellIdentifier } from '../../../stores/effects/database/cell/cell_bd_svc'; +import { CellCache } from '../../../stores/effects/database/cell/cell_cache'; +import { FieldController } from '../../../stores/effects/database/field/field_controller'; +import { CellControllerBuilder } from '../../../stores/effects/database/cell/controller_builder'; +import { DateCellDataPB, FieldType, SelectOptionCellDataPB } from '../../../../services/backend'; +import { useState } from 'react'; + +export const useCell = (cellIdentifier: CellIdentifier, cellCache: CellCache, fieldController: FieldController) => { + const [data, setData] = useState([]); + + const loadCell = async () => { + const builder = new CellControllerBuilder(cellIdentifier, cellCache, fieldController); + const cellController = builder.build(); + cellController.subscribeChanged({ + onCellChanged: (value) => { + if ( + cellIdentifier.fieldType === FieldType.Checklist || + cellIdentifier.fieldType === FieldType.MultiSelect || + cellIdentifier.fieldType === FieldType.SingleSelect + ) { + const v = value.unwrap() as SelectOptionCellDataPB; + setData(v.select_options.map((option) => option.id)); + } else if (cellIdentifier.fieldType === FieldType.DateTime) { + const v = value.unwrap() as DateCellDataPB; + setData([v.date]); + } else { + const v = value.unwrap() as string; + setData([v]); + } + }, + }); + + cellController.getCellData(); + }; + + return { + loadCell, + data, + }; +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts new file mode 100644 index 0000000000..adc75c9b22 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts @@ -0,0 +1,50 @@ +import { useEffect, useState } from 'react'; +import { DatabaseController } from '../../../stores/effects/database/database_controller'; +import { + databaseActions, + DatabaseFieldMap, + IDatabaseColumn, + IDatabaseRow, +} from '../../../stores/reducers/database/slice'; +import { useAppDispatch, useAppSelector } from '../../../stores/store'; +import loadField from './loadField'; +import { FieldInfo } from '../../../stores/effects/database/field/field_controller'; + +export const useDatabase = (viewId: string) => { + const dispatch = useAppDispatch(); + const databaseStore = useAppSelector((state) => state.database); + const boardStore = useAppSelector((state) => state.board); + const [controller, setController] = useState(); + + useEffect(() => { + if (!viewId.length) return; + const c = new DatabaseController(viewId); + setController(c); + + // on unmount dispose the controller + return () => void c.dispose(); + }, [viewId]); + + const loadFields = async (fieldInfos: readonly FieldInfo[]) => { + const fields: DatabaseFieldMap = {}; + const columns: IDatabaseColumn[] = []; + + for (const fieldInfo of fieldInfos) { + const fieldPB = fieldInfo.field; + columns.push({ + fieldId: fieldPB.id, + sort: 'none', + visible: fieldPB.visibility, + }); + + const field = await loadField(viewId, fieldInfo, dispatch); + fields[field.fieldId] = field; + } + + dispatch(databaseActions.updateFields({ fields })); + dispatch(databaseActions.updateColumns({ columns })); + console.log(fields, columns); + }; + + return { loadFields, controller }; +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts new file mode 100644 index 0000000000..3694d3fb84 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts @@ -0,0 +1,32 @@ +import { DatabaseController } from '../../../stores/effects/database/database_controller'; +import { RowController } from '../../../stores/effects/database/row/row_controller'; +import { RowInfo } from '../../../stores/effects/database/row/row_cache'; +import { CellIdentifier } from '../../../stores/effects/database/cell/cell_bd_svc'; +import { useState } from 'react'; + +export const useRow = (viewId: string, databaseController: DatabaseController, rowInfo: RowInfo) => { + const [cells, setCells] = useState<{ fieldId: string; cellIdentifier: CellIdentifier }[]>([]); + + const rowCache = databaseController.databaseViewCache.getRowCache(); + const fieldController = databaseController.fieldController; + const rowController = new RowController(rowInfo, fieldController, rowCache); + + const loadRow = async () => { + const cellsPB = await rowController.loadCells(); + const loadingCells: { fieldId: string; cellIdentifier: CellIdentifier }[] = []; + + for (const [fieldId, cellIdentifier] of cellsPB.entries()) { + loadingCells.push({ + fieldId, + cellIdentifier, + }); + } + + setCells(loadingCells); + }; + + return { + loadRow: loadRow, + cells: cells, + }; +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.hooks.ts index 38f18c3f60..c5c2f42d5a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.hooks.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from 'react'; import { useAppDispatch, useAppSelector } from '../../stores/store'; import { boardActions } from '../../stores/reducers/board/slice'; -import { ICellData, IDatabase, IDatabaseRow, ISelectOption } from '../../stores/reducers/database/slice'; +import { IDatabase, IDatabaseRow, ISelectOption } from '../../stores/reducers/database/slice'; export const useBoard = () => { const dispatch = useAppDispatch(); @@ -15,20 +15,22 @@ export const useBoard = () => { useEffect(() => { setTitle(database.title); - setBoardColumns( - database.fields[groupingFieldId].fieldOptions.selectOptions?.map((groupFieldItem) => { - const rows = database.rows - .filter((row) => row.cells[groupingFieldId].optionIds?.some((so) => so === groupFieldItem.selectOptionId)) - .map((row) => ({ - ...row, - isGhost: false, - })); - return { - ...groupFieldItem, - rows: rows, - }; - }) || [] - ); + if (database.fields[groupingFieldId]) { + setBoardColumns( + database.fields[groupingFieldId].fieldOptions.selectOptions?.map((groupFieldItem) => { + /* const rows = database.rows + .filter((row) => row.cells[groupingFieldId].data?.some((so) => so === groupFieldItem.selectOptionId)) + .map((row) => ({ + ...row, + isGhost: false, + }));*/ + return { + ...groupFieldItem, + rows: [], + }; + }) || [] + ); + } }, [database, groupingFieldId]); const changeGroupingField = (fieldId: string) => { diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx index e4cee56016..bd20cdbf64 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx @@ -1,13 +1,15 @@ import { SettingsSvg } from '../_shared/svg/SettingsSvg'; import { SearchInput } from '../_shared/SearchInput'; -import { useDatabase } from '../_shared/Database.hooks'; import { BoardBlock } from './BoardBlock'; import { NewBoardBlock } from './NewBoardBlock'; -import { IDatabaseRow } from '../../stores/reducers/database/slice'; import { useBoard } from './Board.hooks'; +import { useDatabase } from '../_shared/database-hooks/useDatabase'; +import { useEffect, useState } from 'react'; +import { RowInfo } from '../../stores/effects/database/row/row_cache'; + +export const Board = ({ viewId }: { viewId: string }) => { + const { controller, loadFields } = useDatabase(viewId); -export const Board = () => { - const { database, newField, renameField, newRow } = useDatabase(); const { title, boardColumns, @@ -20,6 +22,24 @@ export const Board = () => { ghostLocation, } = useBoard(); + const [rows, setRows] = useState([]); + + useEffect(() => { + if (!controller) return; + + void (async () => { + controller.subscribe({ + onRowsChanged: (rowInfos) => { + setRows(rowInfos); + }, + onFieldsChanged: (fieldInfos) => { + void loadFields(fieldInfos); + }, + }); + await controller.open(); + })(); + }, [controller]); + return ( <>
@@ -36,16 +56,15 @@ export const Board = () => {
- {database && + {controller && boardColumns?.map((column, index) => ( diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx index 9d5e493d70..03373b58f9 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx @@ -1,24 +1,26 @@ import { Details2Svg } from '../_shared/svg/Details2Svg'; import AddSvg from '../_shared/svg/AddSvg'; -import { DatabaseFieldMap, ICellData, IDatabaseColumn, IDatabaseRow } from '../../stores/reducers/database/slice'; -import { BoardBlockItem } from './BoardBlockItem'; +import { DatabaseFieldMap, IDatabaseColumn, IDatabaseRow } from '../../stores/reducers/database/slice'; +import { BoardCard } from './BoardCard'; +import { RowInfo } from '../../stores/effects/database/row/row_cache'; +import { useEffect } from 'react'; +import { useRow } from '../_shared/database-hooks/useRow'; +import { DatabaseController } from '../../stores/effects/database/database_controller'; export const BoardBlock = ({ + viewId, + controller, title, groupingFieldId, - count, - fields, - columns, rows, startMove, endMove, }: { + viewId: string; + controller: DatabaseController; title: string; groupingFieldId: string; - count: number; - fields: DatabaseFieldMap; - columns: IDatabaseColumn[]; - rows: IDatabaseRow[]; + rows: readonly RowInfo[]; startMove: (id: string) => void; endMove: () => void; }) => { @@ -27,7 +29,7 @@ export const BoardBlock = ({
{title} - ({count}) + ()
{rows.map((row, index) => ( - startMove(row.rowId)} + startMove={() => startMove(row.row.id)} endMove={() => endMove()} - > + > ))}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlockItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx similarity index 67% rename from frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlockItem.tsx rename to frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx index 7741bbd05f..772f23f128 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlockItem.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx @@ -3,22 +3,32 @@ import { Details2Svg } from '../_shared/svg/Details2Svg'; import { FieldType } from '../../../services/backend'; import { getBgColor } from '../_shared/getColor'; import { MouseEventHandler, useEffect, useRef, useState } from 'react'; +import { RowInfo } from '../../stores/effects/database/row/row_cache'; +import { useRow } from '../_shared/database-hooks/useRow'; +import { DatabaseController } from '../../stores/effects/database/database_controller'; +import { useAppSelector } from '../../stores/store'; +import { BoardCell } from './BoardCell'; -export const BoardBlockItem = ({ +export const BoardCard = ({ + viewId, + controller, groupingFieldId, - fields, - columns, + // fields, + // columns, row, startMove, endMove, }: { + viewId: string; + controller: DatabaseController; groupingFieldId: string; - fields: DatabaseFieldMap; - columns: IDatabaseColumn[]; - row: IDatabaseRow; + // fields: DatabaseFieldMap; + // columns: IDatabaseColumn[]; + row: RowInfo; startMove: () => void; endMove: () => void; }) => { + const databaseStore = useAppSelector((state) => state.database); const [isMoving, setIsMoving] = useState(false); const [isDown, setIsDown] = useState(false); const [ghostWidth, setGhostWidth] = useState(0); @@ -43,6 +53,13 @@ export const BoardBlockItem = ({ } }, [el, isMoving]); + const { loadRow, cells } = useRow(viewId, controller, row); + useEffect(() => { + void (async () => { + await loadRow(); + })(); + }, []); + const onMouseMove: MouseEventHandler = (e) => { setGhostLeft(ghostLeft + e.movementX); setGhostTop(ghostTop + e.movementY); @@ -74,31 +91,14 @@ export const BoardBlockItem = ({
- {columns - .filter((column) => column.fieldId !== groupingFieldId) - .map((column, index) => { - switch (fields[column.fieldId].fieldType) { - case FieldType.MultiSelect: - return ( -
- {row.cells[column.fieldId].optionIds?.map((option, indexOption) => { - const selectOptions = fields[column.fieldId].fieldOptions.selectOptions; - const selectedOption = selectOptions?.find((so) => so.selectOptionId === option); - return ( -
- {selectedOption?.title} -
- ); - })} -
- ); - default: - return
{row.cells[column.fieldId].data}
; - } - })} + {cells.map((cell, index) => ( + + ))}
{isMoving && ( diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCell.tsx new file mode 100644 index 0000000000..e0a0dc66cc --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCell.tsx @@ -0,0 +1,23 @@ +import { useCell } from '../_shared/database-hooks/useCell'; +import { CellIdentifier } from '../../stores/effects/database/cell/cell_bd_svc'; +import { CellCache } from '../../stores/effects/database/cell/cell_cache'; +import { FieldController } from '../../stores/effects/database/field/field_controller'; +import {useEffect} from "react"; + +export const BoardCell = ({ + cellIdentifier, + cellCache, + fieldController, +}: { + cellIdentifier: CellIdentifier; + cellCache: CellCache; + fieldController: FieldController; +}) => { + const { loadCell, data } = useCell(cellIdentifier, cellCache, fieldController); + useEffect(() => { + void (async () => { + await loadCell() + })(); + }, []) + return
{data}
; +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts index 25af4535ea..0d417a0f4a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts @@ -3,7 +3,8 @@ import { FieldController, FieldInfo } from './field/field_controller'; import { DatabaseViewCache } from './view/database_view_cache'; import { DatabasePB } from '../../../../services/backend/models/flowy-database/grid_entities'; import { RowChangedReason, RowInfo } from './row/row_cache'; -import { Err, Ok } from 'ts-results'; +import { Err, Ok, Result } from 'ts-results'; +import { FlowyError, RowPB } from '../../../../services/backend'; export type SubscribeCallback = { onViewChanged?: (data: DatabasePB) => void; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/board/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/board/slice.ts index 9a9fe82ab5..dff96c6a31 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/board/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/board/slice.ts @@ -1,6 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -const initialState = 'field1'; +const initialState = ''; export const boardSlice = createSlice({ name: 'board', diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts index 8c83a0c8f6..d959bf7190 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts @@ -1,5 +1,4 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { nanoid } from 'nanoid'; import { FieldType } from '../../../../services/backend/models/flowy-database/field_entities'; import { DateFormat, NumberFormat, SelectOptionColorPB, TimeFormat } from '../../../../services/backend'; @@ -27,24 +26,22 @@ export interface IDatabaseField { export interface IDatabaseColumn { fieldId: string; sort: 'none' | 'asc' | 'desc'; - filter?: any; visible: boolean; } -export interface ICellData { +/*export interface ICellData { rowId: string; fieldId: string; cellId: string; - data: string | number; - optionIds?: string[]; -} + data: string[]; +}*/ -export type DatabaseCellMap = { [keys: string]: ICellData }; +// export type DatabaseCellMap = { [keys: string]: ICellData }; export interface IDatabaseRow { rowId: string; // key(fieldId) -> value(Cell) - cells: DatabaseCellMap; + // cells: DatabaseCellMap; } export type DatabaseFieldMap = { [keys: string]: IDatabaseField }; @@ -56,190 +53,47 @@ export interface IDatabase { columns: IDatabaseColumn[]; } -// key(databaseId) -> value(IDatabase) const initialState: IDatabase = { title: 'Database One', - columns: [ - { - visible: true, - fieldId: 'field1', - sort: 'none', - }, - { - visible: true, - fieldId: 'field2', - sort: 'none', - }, - { - visible: true, - fieldId: 'field3', - sort: 'none', - }, - { - visible: true, - fieldId: 'field4', - sort: 'none', - }, - ], - fields: { - field1: { - title: 'status', - fieldId: 'field1', - fieldType: FieldType.SingleSelect, - fieldOptions: { - selectOptions: [ - { - selectOptionId: 'so1', - title: 'To Do', - color: SelectOptionColorPB.Orange, - }, - { - selectOptionId: 'so2', - title: 'In Progress', - color: SelectOptionColorPB.Green, - }, - { - selectOptionId: 'so3', - title: 'Done', - color: SelectOptionColorPB.Blue, - }, - ], - }, - }, - field2: { - title: 'name', - fieldId: 'field2', - fieldType: FieldType.RichText, - fieldOptions: {}, - }, - field3: { - title: 'percent', - fieldId: 'field3', - fieldType: FieldType.Number, - fieldOptions: { - numberFormat: NumberFormat.Num, - }, - }, - field4: { - title: 'tags', - fieldId: 'field4', - fieldType: FieldType.MultiSelect, - fieldOptions: { - selectOptions: [ - { - selectOptionId: 'f4so1', - title: 'type1', - color: SelectOptionColorPB.Blue, - }, - { - selectOptionId: 'f4so2', - title: 'type2', - color: SelectOptionColorPB.Aqua, - }, - { - selectOptionId: 'f4so3', - title: 'type3', - color: SelectOptionColorPB.Purple, - }, - { - selectOptionId: 'f4so4', - title: 'type4', - color: SelectOptionColorPB.Purple, - }, - { - selectOptionId: 'f4so5', - title: 'type5', - color: SelectOptionColorPB.Purple, - }, - { - selectOptionId: 'f4so6', - title: 'type6', - color: SelectOptionColorPB.Purple, - }, - { - selectOptionId: 'f4so7', - title: 'type7', - color: SelectOptionColorPB.Purple, - }, - ], - }, - }, - }, - rows: [ - { - rowId: 'row1', - cells: { - field1: { - rowId: 'row1', - fieldId: 'field1', - cellId: 'cell11', - data: '', - optionIds: ['so1'], - }, - field2: { - rowId: 'row1', - fieldId: 'field2', - cellId: 'cell12', - data: 'Card 1', - }, - field3: { - rowId: 'row1', - fieldId: 'field3', - cellId: 'cell13', - data: 10, - }, - field4: { - rowId: 'row1', - fieldId: 'field4', - cellId: 'cell14', - data: '', - optionIds: ['f4so2', 'f4so3', 'f4so4', 'f4so5', 'f4so6', 'f4so7'], - }, - }, - }, - { - rowId: 'row2', - cells: { - field1: { - rowId: 'row2', - fieldId: 'field1', - cellId: 'cell21', - data: '', - optionIds: ['so1'], - }, - field2: { - rowId: 'row2', - fieldId: 'field2', - cellId: 'cell22', - data: 'Card 2', - }, - field3: { - rowId: 'row2', - fieldId: 'field3', - cellId: 'cell23', - data: 20, - }, - field4: { - rowId: 'row2', - fieldId: 'field4', - cellId: 'cell24', - data: '', - optionIds: ['f4so1'], - }, - }, - }, - ], + columns: [], + fields: {}, + rows: [], }; export const databaseSlice = createSlice({ name: 'database', initialState: initialState, reducers: { + clear: () => { + return initialState; + }, + + updateRows: (state, action: PayloadAction<{ rows: IDatabaseRow[] }>) => { + return { + ...state, + rows: action.payload.rows, + }; + }, + + updateFields: (state, action: PayloadAction<{ fields: DatabaseFieldMap }>) => { + return { + ...state, + fields: action.payload.fields, + }; + }, + + updateColumns: (state, action: PayloadAction<{ columns: IDatabaseColumn[] }>) => { + return { + ...state, + columns: action.payload.columns, + }; + }, + updateTitle: (state, action: PayloadAction<{ title: string }>) => { state.title = action.payload.title; }, - addField: (state, action: PayloadAction<{ field: IDatabaseField }>) => { + /*addField: (state, action: PayloadAction<{ field: IDatabaseField }>) => { const { field } = action.payload; state.fields[field.fieldId] = field; @@ -253,7 +107,7 @@ export const databaseSlice = createSlice({ cells[field.fieldId] = { rowId: r.rowId, fieldId: field.fieldId, - data: '', + data: [''], cellId: nanoid(6), }; return { @@ -261,15 +115,15 @@ export const databaseSlice = createSlice({ cells: cells, }; }); - }, + },*/ - updateField: (state, action: PayloadAction<{ field: IDatabaseField }>) => { + /*updateField: (state, action: PayloadAction<{ field: IDatabaseField }>) => { const { field } = action.payload; state.fields[field.fieldId] = field; - }, + },*/ - addFieldSelectOption: (state, action: PayloadAction<{ fieldId: string; option: ISelectOption }>) => { + /*addFieldSelectOption: (state, action: PayloadAction<{ fieldId: string; option: ISelectOption }>) => { const { fieldId, option } = action.payload; const field = state.fields[fieldId]; @@ -283,9 +137,9 @@ export const databaseSlice = createSlice({ selectOptions: [option], }; } - }, + },*/ - updateFieldSelectOption: (state, action: PayloadAction<{ fieldId: string; option: ISelectOption }>) => { + /*updateFieldSelectOption: (state, action: PayloadAction<{ fieldId: string; option: ISelectOption }>) => { const { fieldId, option } = action.payload; const field = state.fields[fieldId]; @@ -293,16 +147,16 @@ export const databaseSlice = createSlice({ if (selectOptions) { selectOptions[selectOptions.findIndex((o) => o.selectOptionId === option.selectOptionId)] = option; } - }, + },*/ - addRow: (state) => { + /*addRow: (state) => { const rowId = nanoid(6); const cells: { [keys: string]: ICellData } = {}; Object.keys(state.fields).forEach((id) => { cells[id] = { rowId: rowId, fieldId: id, - data: '', + data: [''], cellId: nanoid(6), }; }); @@ -312,15 +166,15 @@ export const databaseSlice = createSlice({ }; state.rows.push(newRow); - }, + },*/ - updateCellValue: (source, action: PayloadAction<{ cell: ICellData }>) => { + /*updateCellValue: (source, action: PayloadAction<{ cell: ICellData }>) => { const { cell } = action.payload; const row = source.rows.find((r) => r.rowId === cell.rowId); if (row) { row.cells[cell.fieldId] = cell; } - }, + },*/ }, }); diff --git a/frontend/appflowy_tauri/src/appflowy_app/views/BoardPage.tsx b/frontend/appflowy_tauri/src/appflowy_app/views/BoardPage.tsx index 0e2cc8cc19..d533850710 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/views/BoardPage.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/views/BoardPage.tsx @@ -4,19 +4,19 @@ import { Board } from '../components/board/Board'; export const BoardPage = () => { const params = useParams(); - const [databaseId, setDatabaseId] = useState(''); + const [viewId, setViewId] = useState(''); useEffect(() => { if (params?.id?.length) { - // setDatabaseId(params.id); - setDatabaseId('testDb'); + setViewId(params.id); + // setDatabaseId('testDb'); } }, [params]); return (
-

Board

- {databaseId?.length && } +

Board: {viewId}

+ {viewId?.length && }
); }; From 7839ad26c4a3a454fe5c4a6e83d16b3af02b070e Mon Sep 17 00:00:00 2001 From: ascarbek Date: Fri, 3 Mar 2023 18:37:50 +0600 Subject: [PATCH 016/117] fix: initially authenticated and serializable fix --- .../src/appflowy_app/stores/reducers/current-user/slice.ts | 2 +- frontend/appflowy_tauri/src/appflowy_app/stores/store.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts index 2e97d45cd9..b800297ed8 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts @@ -16,7 +16,7 @@ const initialState: ICurrentUser | null = { displayName: 'Me 😃', email: `${nanoid(4)}@gmail.com`, token: nanoid(8), - isAuthenticated: false, + isAuthenticated: true, }; export const currentUserSlice = createSlice({ diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts index cf96a7d625..9e476d875e 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts @@ -33,7 +33,7 @@ const store = configureStore({ [workspaceSlice.name]: workspaceSlice.reducer, [errorSlice.name]: errorSlice.reducer, }, - middleware: (gDM) => gDM().prepend(listenerMiddlewareInstance.middleware), + middleware: (gDM) => gDM({ serializableCheck: false }).prepend(listenerMiddlewareInstance.middleware), }); export { store }; From d0558e4da1c0eaa8febf1bdf2e4f9a769067cb21 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Fri, 3 Mar 2023 19:18:15 +0600 Subject: [PATCH 017/117] fix: ci warning --- .../components/_shared/Database.hooks.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Database.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Database.hooks.ts index d5a4345c92..50de845116 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Database.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/Database.hooks.ts @@ -9,7 +9,7 @@ export const useDatabase = () => { const database = useAppSelector((state) => state.database); const newField = () => { - dispatch( + /* dispatch( databaseActions.addField({ field: { fieldId: nanoid(8), @@ -18,22 +18,25 @@ export const useDatabase = () => { title: 'new field', }, }) - ); + );*/ + console.log('depreciated'); }; const renameField = (fieldId: string, newTitle: string) => { - const field = database.fields[fieldId]; + /* const field = database.fields[fieldId]; field.title = newTitle; dispatch( databaseActions.updateField({ field, }) - ); + );*/ + console.log('depreciated'); }; const newRow = () => { - dispatch(databaseActions.addRow()); + // dispatch(databaseActions.addRow()); + console.log('depreciated'); }; return { From b417fb5fdf7265876f7aca56d5e58b7f91889f02 Mon Sep 17 00:00:00 2001 From: nathan Date: Sat, 4 Mar 2023 19:27:18 +0800 Subject: [PATCH 018/117] ci: compile error --- .../stores/effects/database/cell/cell_controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts index 1e5d45a9b7..89d9446b05 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_controller.ts @@ -118,7 +118,7 @@ class CellDataNotifier extends ChangeNotifier { constructor(cellData: Option) { super(); - this._cellData = Some(cellData); + this._cellData = cellData; } set cellData(data: Option) { From 3afca2b482da42d0e64e7ed74f589c167e75b076 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Sun, 5 Mar 2023 22:19:46 +0600 Subject: [PATCH 019/117] fix: new folder trash overflow --- .../components/layout/NavigationPanel/NavigationPanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx index 119baf795f..a8687c4862 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx @@ -29,7 +29,7 @@ export const NavigationPanel = ({ -
+
{folders.map((folder, index) => ( Date: Sun, 5 Mar 2023 22:28:33 +0600 Subject: [PATCH 020/117] fix: min width for nav panel --- .../components/layout/NavigationPanel/NavigationPanel.tsx | 6 ++++-- .../layout/NavigationPanel/NavigationResizer.tsx | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx index a8687c4862..83ec937665 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx @@ -8,6 +8,8 @@ import { NavigationResizer } from './NavigationResizer'; import { IFolder } from '../../../stores/reducers/folders/slice'; import { IPage } from '../../../stores/reducers/pages/slice'; +const MINIMUM_WIDTH = 200; + export const NavigationPanel = ({ onCollapseNavigationClick, width, @@ -29,7 +31,7 @@ export const NavigationPanel = ({ -
+
{folders.map((folder, index) => (
- + ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationResizer.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationResizer.tsx index 087d3c0d42..cba0c35a8d 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationResizer.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationResizer.tsx @@ -3,13 +3,17 @@ import { useAppDispatch, useAppSelector } from '../../../stores/store'; import { useEffect } from 'react'; import { navigationWidthActions } from '../../../stores/reducers/navigation-width/slice'; -export const NavigationResizer = () => { +export const NavigationResizer = ({ minWidth }: { minWidth: number }) => { const width = useAppSelector((state) => state.navigationWidth); const appDispatch = useAppDispatch(); const { onMouseDown, movementX } = useResizer(); useEffect(() => { - appDispatch(navigationWidthActions.changeWidth(width + movementX)); + if (width + movementX < minWidth) { + appDispatch(navigationWidthActions.changeWidth(minWidth)); + } else { + appDispatch(navigationWidthActions.changeWidth(width + movementX)); + } }, [movementX]); return ( From 543846c241e559bb7e13f46589453dae4cab9b0b Mon Sep 17 00:00:00 2001 From: ascarbek Date: Sun, 5 Mar 2023 23:22:43 +0600 Subject: [PATCH 021/117] fix: nav panel and main panel animation on hide menu --- .../layout/HeaderPanel/Breadcrumbs.tsx | 10 ++++- .../layout/HeaderPanel/HeaderPanel.tsx | 4 +- .../components/layout/MainPanel.tsx | 37 +++++++++++++++++-- .../NavigationPanel/NavigationPanel.hooks.ts | 12 ++++++ .../NavigationPanel/NavigationPanel.tsx | 18 +++++++-- .../appflowy_app/components/layout/Screen.tsx | 33 +++++++---------- 6 files changed, 84 insertions(+), 30 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/Breadcrumbs.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/Breadcrumbs.tsx index 2a0ef61101..e4258f30b3 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/Breadcrumbs.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/Breadcrumbs.tsx @@ -1,7 +1,15 @@ -export const Breadcrumbs = () => { +import { ShowMenuSvg } from '../../_shared/svg/ShowMenuSvg'; + +export const Breadcrumbs = ({ menuHidden, onShowMenuClick }: { menuHidden: boolean; onShowMenuClick: () => void }) => { return (
+ {menuHidden && ( + + )} + diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/HeaderPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/HeaderPanel.tsx index 37a095afdb..f870d6fa2d 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/HeaderPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/HeaderPanel.tsx @@ -1,10 +1,10 @@ import { Breadcrumbs } from './Breadcrumbs'; import { PageOptions } from './PageOptions'; -export const HeaderPanel = () => { +export const HeaderPanel = ({ menuHidden, onShowMenuClick }: { menuHidden: boolean; onShowMenuClick: () => void }) => { return (
- +
); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/MainPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/MainPanel.tsx index 0fd02f9113..b181693fd1 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/MainPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/MainPanel.tsx @@ -1,11 +1,40 @@ -import { ReactNode } from 'react'; +import { ReactNode, useEffect, useState } from 'react'; import { HeaderPanel } from './HeaderPanel/HeaderPanel'; import { FooterPanel } from './FooterPanel'; -export const MainPanel = ({ children }: { children: ReactNode }) => { +const ANIMATION_DURATION = 300; + +export const MainPanel = ({ + left, + menuHidden, + onShowMenuClick, + children, +}: { + left: number; + menuHidden: boolean; + onShowMenuClick: () => void; + children: ReactNode; +}) => { + const [animation, setAnimation] = useState(false); + useEffect(() => { + if (!menuHidden) { + setTimeout(() => { + setAnimation(false); + }, ANIMATION_DURATION); + } else { + setAnimation(true); + } + }, [menuHidden]); + return ( -
- +
+
{children}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts index 26c8d40011..4b2f9bde2d 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts @@ -14,6 +14,7 @@ export const useNavigationPanelHooks = function () { const width = useAppSelector((state) => state.navigationWidth); const [navigationPanelFixed, setNavigationPanelFixed] = useState(true); const [slideInFloatingPanel, setSlideInFloatingPanel] = useState(true); + const [menuHidden, setMenuHidden] = useState(false); const navigate = useNavigate(); @@ -28,6 +29,14 @@ export const useNavigationPanelHooks = function () { const [floatingPanelWidth, setFloatingPanelWidth] = useState(0); + const onHideMenuClick = () => { + setMenuHidden(true); + }; + + const onShowMenuClick = () => { + setMenuHidden(false); + }; + const onPageClick = (page: IPage) => { let pageTypeRoute = (() => { switch (page.pageType) { @@ -69,5 +78,8 @@ export const useNavigationPanelHooks = function () { onScreenMouseMove, slideInFloatingPanel, setFloatingPanelWidth, + menuHidden, + onHideMenuClick, + onShowMenuClick, }; }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx index 83ec937665..859a8e307f 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx @@ -9,15 +9,18 @@ import { IFolder } from '../../../stores/reducers/folders/slice'; import { IPage } from '../../../stores/reducers/pages/slice'; const MINIMUM_WIDTH = 200; +const ANIMATION_DURATION = 300; export const NavigationPanel = ({ - onCollapseNavigationClick, + onHideMenuClick, + menuHidden, width, folders, pages, onPageClick, }: { - onCollapseNavigationClick: () => void; + onHideMenuClick: () => void; + menuHidden: boolean; width: number; folders: IFolder[]; pages: IPage[]; @@ -25,9 +28,16 @@ export const NavigationPanel = ({ }) => { return ( <> -
+
- + diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx index f589cb2fe5..265eefedcc 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx @@ -26,30 +26,25 @@ export const Screen = ({ children }: { children: ReactNode }) => { onScreenMouseMove, slideInFloatingPanel, setFloatingPanelWidth, + onHideMenuClick, + onShowMenuClick, + menuHidden, } = useNavigationPanelHooks(); return (
- {navigationPanelFixed ? ( - - ) : ( - - )} + - {children} + + {children} +
); }; From e297769ac2ed1a8dd3ca253b41bb414a6f95a306 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Sun, 5 Mar 2023 23:34:46 +0600 Subject: [PATCH 022/117] fix: highlight active page --- .../layout/NavigationPanel/NavigationPanel.hooks.ts | 6 +++++- .../layout/NavigationPanel/PageItem.hooks.ts | 4 +++- .../components/layout/NavigationPanel/PageItem.tsx | 5 ++++- .../stores/reducers/activePageId/slice.ts | 12 ++++++++++++ .../appflowy_tauri/src/appflowy_app/stores/store.ts | 2 ++ 5 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/stores/reducers/activePageId/slice.ts diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts index 4b2f9bde2d..1b7a28c655 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts @@ -1,14 +1,16 @@ -import { useAppSelector } from '../../../stores/store'; +import { useAppDispatch, useAppSelector } from '../../../stores/store'; import { useNavigate } from 'react-router-dom'; import { IPage } from '../../../stores/reducers/pages/slice'; import { ViewLayoutTypePB } from '../../../../services/backend'; import { MouseEventHandler, useState } from 'react'; +import { activePageIdActions } from '../../../stores/reducers/activePageId/slice'; // number of pixels from left side of screen to show hidden navigation panel const FLOATING_PANEL_SHOW_WIDTH = 10; const FLOATING_PANEL_HIDE_EXTRA_WIDTH = 10; export const useNavigationPanelHooks = function () { + const dispatch = useAppDispatch(); const folders = useAppSelector((state) => state.folders); const pages = useAppSelector((state) => state.pages); const width = useAppSelector((state) => state.navigationWidth); @@ -52,6 +54,8 @@ export const useNavigationPanelHooks = function () { } })(); + dispatch(activePageIdActions.setActivePageId(page.id)); + navigate(`/page/${pageTypeRoute}/${page.id}`); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts index 77e53086be..9e608071e1 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts @@ -1,5 +1,5 @@ import { IPage, pagesActions } from '../../../stores/reducers/pages/slice'; -import { useAppDispatch } from '../../../stores/store'; +import { useAppDispatch, useAppSelector } from '../../../stores/store'; import { useState } from 'react'; import { nanoid } from 'nanoid'; import { ViewBackendService } from '../../../stores/effects/folder/view/view_bd_svc'; @@ -9,6 +9,7 @@ export const usePageEvents = (page: IPage) => { const appDispatch = useAppDispatch(); const [showPageOptions, setShowPageOptions] = useState(false); const [showRenamePopup, setShowRenamePopup] = useState(false); + const activePageId = useAppSelector((state) => state.activePageId); const viewBackendService: ViewBackendService = new ViewBackendService(page.id); const error = useError(); @@ -69,5 +70,6 @@ export const usePageEvents = (page: IPage) => { duplicatePage, closePopup, closeRenamePopup, + activePageId, }; }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx index 7b1186f95d..0d0affe33f 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx @@ -20,13 +20,16 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () = duplicatePage, closePopup, closeRenamePopup, + activePageId, } = usePageEvents(page); return (
onPageClick()} - className={'flex cursor-pointer items-center justify-between rounded-lg py-2 pl-8 pr-4 hover:bg-surface-2 '} + className={`flex cursor-pointer items-center justify-between rounded-lg py-2 pl-8 pr-4 hover:bg-surface-2 ${ + activePageId === page.id ? 'bg-surface-2' : '' + }`} > -
+
@@ -104,6 +98,7 @@ export const FolderItem = ({ onDeleteClick={() => deleteFolder()} onDuplicateClick={() => duplicateFolder()} onClose={() => closePopup()} + top={popupY - 124 + 40} > )} {showNewPageOptions && ( @@ -112,6 +107,7 @@ export const FolderItem = ({ onBoardClick={() => onAddNewBoardPage()} onGridClick={() => onAddNewGridPage()} onClose={() => closePopup()} + top={popupY - 124 + 40} > )} {showRenamePopup && ( @@ -119,6 +115,7 @@ export const FolderItem = ({ value={folder.title} onChange={(newTitle) => changeFolderTitle(newTitle)} onClose={closeRenamePopup} + top={popupY - 124 + 40} > )}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavItemOptionsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavItemOptionsPopup.tsx index 8e195b052a..f167623399 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavItemOptionsPopup.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavItemOptionsPopup.tsx @@ -8,11 +8,13 @@ export const NavItemOptionsPopup = ({ onDeleteClick, onDuplicateClick, onClose, + top, }: { onRenameClick: () => void; onDeleteClick: () => void; onDuplicateClick: () => void; onClose?: () => void; + top: number; }) => { const items: IPopupItem[] = [ { @@ -48,7 +50,8 @@ export const NavItemOptionsPopup = ({ onClose && onClose()} items={items} - className={'absolute right-0 top-[40px] z-10'} + className={`absolute right-0`} + style={{ top: `${top}px` }} > ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx index 9db50b33ce..683724ea5b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx @@ -7,7 +7,7 @@ import { NavigationResizer } from './NavigationResizer'; import { IFolder } from '../../../stores/reducers/folders/slice'; import { IPage } from '../../../stores/reducers/pages/slice'; import { useNavigate } from 'react-router-dom'; -import React, { useEffect, useRef } from 'react'; +import React, { useRef } from 'react'; import { useDispatch } from 'react-redux'; import { useAppSelector } from '../../../stores/store'; import { ANIMATION_DURATION, NAV_PANEL_MINIMUM_WIDTH } from '../../_shared/constants'; @@ -46,8 +46,10 @@ export const NavigationPanel = ({
-
- +
+
+ +
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NewPagePopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NewPagePopup.tsx index 8547ced6f4..5b74082907 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NewPagePopup.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NewPagePopup.tsx @@ -8,11 +8,13 @@ export const NewPagePopup = ({ onGridClick, onBoardClick, onClose, + top, }: { onDocumentClick: () => void; onGridClick: () => void; onBoardClick: () => void; onClose?: () => void; + top: number; }) => { const items: IPopupItem[] = [ { @@ -48,7 +50,8 @@ export const NewPagePopup = ({ onClose && onClose()} items={items} - className={'absolute right-0 top-[40px] z-10'} + className={'absolute right-0'} + style={{ top: `${top}px` }} > ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx index d5871fc742..550ea35f63 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx @@ -8,7 +8,7 @@ import { Button } from '../../_shared/Button'; import { usePageEvents } from './PageItem.hooks'; import { RenamePopup } from './RenamePopup'; import { ViewLayoutTypePB } from '../../../../services/backend'; -import { useEffect, useRef } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { PAGE_ITEM_HEIGHT } from '../../_shared/constants'; export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () => void }) => { @@ -32,8 +32,17 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () = setOffsetTop(el.current?.offsetTop || 0); }, [el.current]); + const [popupY, setPopupY] = useState(0); + + useEffect(() => { + if (showPageOptions && el.current) { + const { top } = el.current.getBoundingClientRect(); + setPopupY(top); + } + }, [showPageOptions]); + return ( -
+
onPageClick()} className={`flex cursor-pointer items-center justify-between rounded-lg pl-8 pr-4 hover:bg-surface-2 ${ @@ -51,7 +60,7 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () = {page.title} -
+
@@ -63,6 +72,7 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () = onDeleteClick={() => deletePage()} onDuplicateClick={() => duplicatePage()} onClose={() => closePopup()} + top={popupY - 124 + 40} > )} {showRenamePopup && ( diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/RenamePopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/RenamePopup.tsx index e5e3a893e9..1efe2387e4 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/RenamePopup.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/RenamePopup.tsx @@ -6,11 +6,13 @@ export const RenamePopup = ({ onChange, onClose, className = '', + top, }: { value: string; onChange: (newTitle: string) => void; onClose: () => void; className?: string; + top?: number; }) => { const ref = useRef(null); const inputRef = useRef(null); @@ -32,6 +34,7 @@ export const RenamePopup = ({ className={ 'absolute left-[50px] top-[40px] z-10 flex w-[300px] rounded bg-white py-1 px-1.5 shadow-md ' + className } + style={{ top: `${top}px` }} > ) { return state.map((f) => (f.id === action.payload.id ? { ...f, offsetTop: action.payload.offset } : f)); }, + toggleShowPages(state, action: PayloadAction<{ id: string }>) { + return state.map((f) => (f.id === action.payload.id ? { ...f, showPages: !f.showPages } : f)); + }, }, }); From f556e50be40fb84b0de9a391261e5840f31c8eed Mon Sep 17 00:00:00 2001 From: ascarbek Date: Thu, 9 Mar 2023 22:54:38 +0600 Subject: [PATCH 035/117] fix: page rename position --- .../components/layout/NavigationPanel/PageItem.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx index 550ea35f63..7e07d06316 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx @@ -35,11 +35,11 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () = const [popupY, setPopupY] = useState(0); useEffect(() => { - if (showPageOptions && el.current) { + if (el.current) { const { top } = el.current.getBoundingClientRect(); setPopupY(top); } - }, [showPageOptions]); + }, [showPageOptions, showRenamePopup]); return (
@@ -80,6 +80,7 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () = value={page.title} onChange={(newTitle) => changePageTitle(newTitle)} onClose={closeRenamePopup} + top={popupY - 124 + 40} > )}
From ad0a6d01d25f46b966607e4479c2f75838973947 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Thu, 9 Mar 2023 23:04:31 +0600 Subject: [PATCH 036/117] chore: remove offset top --- .../components/layout/NavigationPanel/FolderItem.hooks.ts | 5 ----- .../components/layout/NavigationPanel/FolderItem.tsx | 5 ----- .../components/layout/NavigationPanel/PageItem.hooks.ts | 5 ----- .../components/layout/NavigationPanel/PageItem.tsx | 5 ----- .../src/appflowy_app/components/layout/Screen.tsx | 1 - .../src/appflowy_app/stores/reducers/folders/slice.ts | 4 ---- .../src/appflowy_app/stores/reducers/pages/slice.ts | 4 ---- 7 files changed, 29 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts index 510d9a526b..642e75f4e4 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts @@ -202,10 +202,6 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { } }; - const setOffsetTop = (v: number) => { - foldersActions.setOffsetTop({ id: folder.id, offset: v }); - }; - return { showPages, onFolderNameClick, @@ -227,6 +223,5 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { closePopup, folderHeight, - setOffsetTop, }; }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.tsx index 414104daeb..c1d87f2a5b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.tsx @@ -42,17 +42,12 @@ export const FolderItem = ({ closePopup, folderHeight, - setOffsetTop, } = useFolderEvents(folder, pages); const [popupY, setPopupY] = useState(0); const el = useRef(null); - useEffect(() => { - setOffsetTop(el.current?.offsetTop || 0); - }, [el, showPages]); - useEffect(() => { if (el.current) { const { top } = el.current.getBoundingClientRect(); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts index f01752f5f1..9e608071e1 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts @@ -60,10 +60,6 @@ export const usePageEvents = (page: IPage) => { setShowRenamePopup(false); }; - const setOffsetTop = (v: number) => { - pagesActions.setOffsetTop({ id: page.id, offset: v }); - }; - return { showPageOptions, onPageOptionsClick, @@ -75,6 +71,5 @@ export const usePageEvents = (page: IPage) => { closePopup, closeRenamePopup, activePageId, - setOffsetTop, }; }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx index 7e07d06316..6085fb2a8c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx @@ -23,15 +23,10 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () = closePopup, closeRenamePopup, activePageId, - setOffsetTop, } = usePageEvents(page); const el = useRef(null); - useEffect(() => { - setOffsetTop(el.current?.offsetTop || 0); - }, [el.current]); - const [popupY, setPopupY] = useState(0); useEffect(() => { diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx index 265eefedcc..c4e6316ab4 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx @@ -2,7 +2,6 @@ import React, { ReactNode, useEffect } from 'react'; import { NavigationPanel } from './NavigationPanel/NavigationPanel'; import { MainPanel } from './MainPanel'; import { useNavigationPanelHooks } from './NavigationPanel/NavigationPanel.hooks'; -import { NavigationFloatingPanel } from './NavigationPanel/NavigationFloatingPanel'; import { useWorkspace } from './Workspace.hooks'; import { useAppSelector } from '../../stores/store'; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/slice.ts index 609988f347..31cc72b05a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/slice.ts @@ -3,7 +3,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; export interface IFolder { id: string; title: string; - offsetTop?: number; showPages?: boolean; } @@ -25,9 +24,6 @@ export const foldersSlice = createSlice({ clearFolders() { return []; }, - setOffsetTop(state, action: PayloadAction<{ id: string; offset: number }>) { - return state.map((f) => (f.id === action.payload.id ? { ...f, offsetTop: action.payload.offset } : f)); - }, toggleShowPages(state, action: PayloadAction<{ id: string }>) { return state.map((f) => (f.id === action.payload.id ? { ...f, showPages: !f.showPages } : f)); }, diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts index b0459d98ce..9c7700d11b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts @@ -6,7 +6,6 @@ export interface IPage { title: string; pageType: ViewLayoutTypePB; folderId: string; - offsetTop?: number; } const initialState: IPage[] = []; @@ -32,9 +31,6 @@ export const pagesSlice = createSlice({ clearPages() { return []; }, - setOffsetTop(state, action: PayloadAction<{ id: string; offset: number }>) { - return state.map((page) => (page.id === action.payload.id ? { ...page, offsetTop: action.payload.offset } : page)); - }, }, }); From 6304c7d95bd751e33786d93384b6b8f15e231982 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Fri, 10 Mar 2023 16:59:11 +0600 Subject: [PATCH 037/117] chore: remove floating menu functions --- .../NavigationPanel/NavigationPanel.hooks.ts | 34 +------------------ .../appflowy_app/components/layout/Screen.tsx | 18 ++-------- 2 files changed, 3 insertions(+), 49 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts index a370f18f4d..7020740631 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts @@ -2,35 +2,18 @@ import { useAppDispatch, useAppSelector } from '../../../stores/store'; import { useNavigate } from 'react-router-dom'; import { IPage } from '../../../stores/reducers/pages/slice'; import { ViewLayoutTypePB } from '../../../../services/backend'; -import { MouseEventHandler, useState } from 'react'; +import { useState } from 'react'; import { activePageIdActions } from '../../../stores/reducers/activePageId/slice'; -// number of pixels from left side of screen to show hidden navigation panel -const FLOATING_PANEL_SHOW_WIDTH = 10; -const FLOATING_PANEL_HIDE_EXTRA_WIDTH = 10; - export const useNavigationPanelHooks = function () { const dispatch = useAppDispatch(); const folders = useAppSelector((state) => state.folders); const pages = useAppSelector((state) => state.pages); const width = useAppSelector((state) => state.navigationWidth); - const [navigationPanelFixed, setNavigationPanelFixed] = useState(true); - const [slideInFloatingPanel, setSlideInFloatingPanel] = useState(true); const [menuHidden, setMenuHidden] = useState(false); const navigate = useNavigate(); - const onCollapseNavigationClick = () => { - setSlideInFloatingPanel(true); - setNavigationPanelFixed(false); - }; - - const onFixNavigationClick = () => { - setNavigationPanelFixed(true); - }; - - const [floatingPanelWidth, setFloatingPanelWidth] = useState(0); - const onHideMenuClick = () => { setMenuHidden(true); }; @@ -59,26 +42,11 @@ export const useNavigationPanelHooks = function () { navigate(`/page/${pageTypeRoute}/${page.id}`); }; - const onScreenMouseMove: MouseEventHandler = (e) => { - if (e.screenX <= FLOATING_PANEL_SHOW_WIDTH) { - setSlideInFloatingPanel(true); - } else if (e.screenX > floatingPanelWidth + FLOATING_PANEL_HIDE_EXTRA_WIDTH) { - setSlideInFloatingPanel(false); - } - }; - return { width, folders, pages, - navigate, onPageClick, - onCollapseNavigationClick, - onFixNavigationClick, - navigationPanelFixed, - onScreenMouseMove, - slideInFloatingPanel, - setFloatingPanelWidth, menuHidden, onHideMenuClick, onShowMenuClick, diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx index c4e6316ab4..19f8e97542 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/Screen.tsx @@ -14,24 +14,10 @@ export const Screen = ({ children }: { children: ReactNode }) => { })(); }, [currentUser.isAuthenticated]); - const { - width, - folders, - pages, - onPageClick, - onCollapseNavigationClick, - onFixNavigationClick, - navigationPanelFixed, - onScreenMouseMove, - slideInFloatingPanel, - setFloatingPanelWidth, - onHideMenuClick, - onShowMenuClick, - menuHidden, - } = useNavigationPanelHooks(); + const { width, folders, pages, onPageClick, onHideMenuClick, onShowMenuClick, menuHidden } = useNavigationPanelHooks(); return ( -
+
Date: Fri, 10 Mar 2023 18:33:54 +0600 Subject: [PATCH 038/117] chore: scroll down to new page --- .../components/_shared/constants.ts | 1 + .../NavigationPanel/FolderItem.hooks.ts | 11 +++- .../NavigationPanel/NavigationPanel.tsx | 52 +++++++++++++++++-- .../stores/reducers/folders/slice.ts | 4 +- 4 files changed, 61 insertions(+), 7 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/constants.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/constants.ts index 24909b26e1..48e51e7f9a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/constants.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/constants.ts @@ -1,4 +1,5 @@ export const INITIAL_FOLDER_HEIGHT = 40; +export const FOLDER_MARGIN = 16; export const PAGE_ITEM_HEIGHT = 40; export const ANIMATION_DURATION = 300; export const NAV_PANEL_MINIMUM_WIDTH = 200; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts index 642e75f4e4..cf96e2a085 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts @@ -65,7 +65,6 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { }, [pages]); const onFolderNameClick = () => { - appDispatch(foldersActions.toggleShowPages({ id: folder.id })); if (showPages) { setFolderHeight(`${INITIAL_FOLDER_HEIGHT}px`); } else { @@ -144,6 +143,8 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { }) ); + setShowPages(true); + appDispatch(activePageIdActions.setActivePageId(newView.id)); navigate(`/page/document/${newView.id}`); @@ -160,6 +161,8 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { layoutType: ViewLayoutTypePB.Board, }); + setShowPages(true); + appDispatch( pagesActions.addPage({ folderId: folder.id, @@ -185,6 +188,8 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { layoutType: ViewLayoutTypePB.Grid, }); + setShowPages(true); + appDispatch( pagesActions.addPage({ folderId: folder.id, @@ -202,6 +207,10 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { } }; + useEffect(() => { + appDispatch(foldersActions.setShowPages({ id: folder.id, showPages: showPages })); + }, [showPages]); + return { showPages, onFolderNameClick, diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx index 683724ea5b..5a35137e9b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx @@ -7,10 +7,16 @@ import { NavigationResizer } from './NavigationResizer'; import { IFolder } from '../../../stores/reducers/folders/slice'; import { IPage } from '../../../stores/reducers/pages/slice'; import { useNavigate } from 'react-router-dom'; -import React, { useRef } from 'react'; +import React, { useEffect, useRef } from 'react'; import { useDispatch } from 'react-redux'; import { useAppSelector } from '../../../stores/store'; -import { ANIMATION_DURATION, NAV_PANEL_MINIMUM_WIDTH } from '../../_shared/constants'; +import { + ANIMATION_DURATION, + FOLDER_MARGIN, + INITIAL_FOLDER_HEIGHT, + NAV_PANEL_MINIMUM_WIDTH, + PAGE_ITEM_HEIGHT, +} from '../../_shared/constants'; export const NavigationPanel = ({ onHideMenuClick, @@ -33,6 +39,44 @@ export const NavigationPanel = ({ const pagesStore = useAppSelector((state) => state.pages); const activePageId = useAppSelector((state) => state.activePageId); + useEffect(() => { + setTimeout(() => { + if (!el.current) return; + if (!activePageId?.length) return; + const activePage = pagesStore.find((page) => page.id === activePageId); + if (!activePage) return; + + const folderIndex = foldersStore.findIndex((folder) => folder.id === activePage.folderId); + if (folderIndex === -1) return; + + let height = 0; + for (let i = 0; i < folderIndex; i++) { + height += INITIAL_FOLDER_HEIGHT + FOLDER_MARGIN; + if (foldersStore[i].showPages === true) { + height += pagesStore.filter((p) => p.folderId === foldersStore[i].id).length * PAGE_ITEM_HEIGHT; + } + } + + height += INITIAL_FOLDER_HEIGHT + FOLDER_MARGIN / 2; + + const pageIndex = pagesStore + .filter((p) => p.folderId === foldersStore[folderIndex].id) + .findIndex((p) => p.id === activePageId); + for (let i = 0; i <= pageIndex; i++) { + height += PAGE_ITEM_HEIGHT; + } + + const elHeight = el.current.getBoundingClientRect().height; + const scrollTop = el.current.scrollTop; + + console.log(`scrollTop: ${scrollTop}, elHeight: ${elHeight.toFixed(0)}, height: ${height}`); + + if (scrollTop + elHeight < height) { + el.current.scrollTo(0, height - elHeight); + } + }, ANIMATION_DURATION); + }, [activePageId]); + return ( <>
-
-
+
+
diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/slice.ts index 31cc72b05a..80d93d596f 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/slice.ts @@ -24,8 +24,8 @@ export const foldersSlice = createSlice({ clearFolders() { return []; }, - toggleShowPages(state, action: PayloadAction<{ id: string }>) { - return state.map((f) => (f.id === action.payload.id ? { ...f, showPages: !f.showPages } : f)); + setShowPages(state, action: PayloadAction<{ id: string; showPages: boolean }>) { + return state.map((f) => (f.id === action.payload.id ? { ...f, showPages: action.payload.showPages } : f)); }, }, }); From 7e3273c7084bcaeea8b86d601c05b3e50a09f4d6 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Fri, 10 Mar 2023 18:58:14 +0600 Subject: [PATCH 039/117] chore: smooth scroll and scroll to new folder --- .../layout/NavigationPanel/NavigationPanel.tsx | 17 ++++++++++++++--- .../layout/NavigationPanel/NewFolderButton.tsx | 10 ++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx index 5a35137e9b..245175391c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx @@ -7,7 +7,7 @@ import { NavigationResizer } from './NavigationResizer'; import { IFolder } from '../../../stores/reducers/folders/slice'; import { IPage } from '../../../stores/reducers/pages/slice'; import { useNavigate } from 'react-router-dom'; -import React, { useEffect, useRef } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { useDispatch } from 'react-redux'; import { useAppSelector } from '../../../stores/store'; import { @@ -38,6 +38,7 @@ export const NavigationPanel = ({ const foldersStore = useAppSelector((state) => state.folders); const pagesStore = useAppSelector((state) => state.pages); const activePageId = useAppSelector((state) => state.activePageId); + const [maxHeight, setMaxHeight] = useState(0); useEffect(() => { setTimeout(() => { @@ -72,11 +73,21 @@ export const NavigationPanel = ({ console.log(`scrollTop: ${scrollTop}, elHeight: ${elHeight.toFixed(0)}, height: ${height}`); if (scrollTop + elHeight < height) { - el.current.scrollTo(0, height - elHeight); + el.current.scrollTo({ top: height - elHeight, behavior: 'smooth' }); } }, ANIMATION_DURATION); }, [activePageId]); + useEffect(() => { + setMaxHeight(foldersStore.length * (INITIAL_FOLDER_HEIGHT + FOLDER_MARGIN) + pagesStore.length * PAGE_ITEM_HEIGHT); + }, [foldersStore, pagesStore]); + + const scrollDown = () => { + setTimeout(() => { + el?.current?.scrollTo({ top: maxHeight, behavior: 'smooth' }); + }, ANIMATION_DURATION); + }; + return ( <>
{/*New Folder Button*/} - +
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NewFolderButton.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NewFolderButton.tsx index 4c487796c7..7c1df82c26 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NewFolderButton.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NewFolderButton.tsx @@ -1,11 +1,17 @@ import AddSvg from '../../_shared/svg/AddSvg'; import { useNewFolder } from './NewFolderButton.hooks'; -export const NewFolderButton = () => { +export const NewFolderButton = ({ scrollDown }: { scrollDown: () => void }) => { const { onNewFolder } = useNewFolder(); return ( - -
-
- Getting Started - / - Read Me +
+ {folderName} + / + {pageName}
); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx index 245175391c..ede89094d9 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx @@ -70,8 +70,6 @@ export const NavigationPanel = ({ const elHeight = el.current.getBoundingClientRect().height; const scrollTop = el.current.scrollTop; - console.log(`scrollTop: ${scrollTop}, elHeight: ${elHeight.toFixed(0)}, height: ${height}`); - if (scrollTop + elHeight < height) { el.current.scrollTo({ top: height - elHeight, behavior: 'smooth' }); } From 268b6ce9268e8fa1918edd29bd02b499b5bc1ab5 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Sat, 11 Mar 2023 20:57:25 +0600 Subject: [PATCH 041/117] chore: back and forward buttons nav scroll fix --- frontend/appflowy_tauri/package.json | 2 +- .../layout/HeaderPanel/Breadcrumbs.tsx | 37 ++++++------------- .../NavigationPanel/FolderItem.hooks.ts | 8 ---- .../NavigationPanel/NavigationPanel.hooks.ts | 6 +-- .../NavigationPanel/NavigationPanel.tsx | 16 +++++--- .../layout/NavigationPanel/PageItem.hooks.ts | 15 ++++++-- .../stores/reducers/activePageId/slice.ts | 12 ------ .../src/appflowy_app/stores/store.ts | 2 - 8 files changed, 36 insertions(+), 62 deletions(-) delete mode 100644 frontend/appflowy_tauri/src/appflowy_app/stores/reducers/activePageId/slice.ts diff --git a/frontend/appflowy_tauri/package.json b/frontend/appflowy_tauri/package.json index e7511d6e1d..80a652f162 100644 --- a/frontend/appflowy_tauri/package.json +++ b/frontend/appflowy_tauri/package.json @@ -9,7 +9,7 @@ "preview": "vite preview", "format": "prettier --write .", "test:code": "eslint --max-warnings=0 --ext .js,.ts,.tsx .", - "test:errors": "eslint --quiet --ext .js,.ts,.tsx .", + "test:errors": "tsc --noEmit", "test:prettier": "yarn prettier --list-different src", "tauri:clean": "cargo make --cwd .. tauri_clean", "tauri:dev": "tauri dev", diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/Breadcrumbs.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/Breadcrumbs.tsx index a055e5f1c4..9e5e608848 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/Breadcrumbs.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/HeaderPanel/Breadcrumbs.tsx @@ -2,44 +2,29 @@ import { ShowMenuSvg } from '../../_shared/svg/ShowMenuSvg'; import { useEffect, useState } from 'react'; import { useAppSelector } from '../../../stores/store'; import { useLocation } from 'react-router-dom'; -import { useDispatch } from 'react-redux'; -import { activePageIdActions } from '../../../stores/reducers/activePageId/slice'; export const Breadcrumbs = ({ menuHidden, onShowMenuClick }: { menuHidden: boolean; onShowMenuClick: () => void }) => { - const dispatch = useDispatch(); const [folderName, setFolderName] = useState(''); const [pageName, setPageName] = useState(''); - const activePageId = useAppSelector((state) => state.activePageId); + const [activePageId, setActivePageId] = useState(''); + const currentLocation = useLocation(); const pagesStore = useAppSelector((state) => state.pages); const foldersStore = useAppSelector((state) => state.folders); - const [pageHistory, setPageHistory] = useState([]); - const [historyIndex, setHistoryIndex] = useState(0); + + useEffect(() => { + const { pathname } = currentLocation; + const parts = pathname.split('/'); + const pageId = parts[parts.length - 1]; + setActivePageId(pageId); + }, [currentLocation]); useEffect(() => { const page = pagesStore.find((p) => p.id === activePageId); const folder = foldersStore.find((f) => f.id === page?.folderId); setFolderName(folder?.title || ''); setPageName(page?.title || ''); - setPageHistory([...pageHistory, activePageId]); }, [pagesStore, foldersStore, activePageId]); - const currentLocation = useLocation(); - - useEffect(() => { - // if there is no active page, we should try to get the page id from the url - if (!activePageId?.length) { - const { pathname } = currentLocation; - const parts = pathname.split('/'); - // `/"page"/{pageType}/{pageId}` - if (parts.length !== 4) return; - - const pageId = parts[parts.length - 1]; - // const pageType = parts[parts.length - 2]; - - dispatch(activePageIdActions.setActivePageId(pageId)); - } - }, [activePageId, currentLocation]); - return (
@@ -50,10 +35,10 @@ export const Breadcrumbs = ({ menuHidden, onShowMenuClick }: { menuHidden: boole )}
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts index cf96e2a085..3c38ab70cd 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts @@ -7,14 +7,12 @@ import { AppBackendService } from '../../../stores/effects/folder/app/app_bd_svc import { WorkspaceBackendService } from '../../../stores/effects/folder/workspace/workspace_bd_svc'; import { useError } from '../../error/Error.hooks'; import { AppObserver } from '../../../stores/effects/folder/app/app_observer'; -import { activePageIdActions } from '../../../stores/reducers/activePageId/slice'; import { useNavigate } from 'react-router-dom'; import { INITIAL_FOLDER_HEIGHT, PAGE_ITEM_HEIGHT } from '../../_shared/constants'; export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { const appDispatch = useAppDispatch(); const workspace = useAppSelector((state) => state.workspace); - const foldersStore = useAppSelector((state) => state.folders); const navigate = useNavigate(); @@ -145,8 +143,6 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { setShowPages(true); - appDispatch(activePageIdActions.setActivePageId(newView.id)); - navigate(`/page/document/${newView.id}`); } catch (e: any) { error.showError(e?.message); @@ -172,8 +168,6 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { }) ); - appDispatch(activePageIdActions.setActivePageId(newView.id)); - navigate(`/page/board/${newView.id}`); } catch (e: any) { error.showError(e?.message); @@ -199,8 +193,6 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => { }) ); - appDispatch(activePageIdActions.setActivePageId(newView.id)); - navigate(`/page/grid/${newView.id}`); } catch (e: any) { error.showError(e?.message); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts index 7020740631..1387291293 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts @@ -1,12 +1,10 @@ -import { useAppDispatch, useAppSelector } from '../../../stores/store'; +import { useAppSelector } from '../../../stores/store'; import { useNavigate } from 'react-router-dom'; import { IPage } from '../../../stores/reducers/pages/slice'; import { ViewLayoutTypePB } from '../../../../services/backend'; import { useState } from 'react'; -import { activePageIdActions } from '../../../stores/reducers/activePageId/slice'; export const useNavigationPanelHooks = function () { - const dispatch = useAppDispatch(); const folders = useAppSelector((state) => state.folders); const pages = useAppSelector((state) => state.pages); const width = useAppSelector((state) => state.navigationWidth); @@ -37,8 +35,6 @@ export const useNavigationPanelHooks = function () { } })(); - dispatch(activePageIdActions.setActivePageId(page.id)); - navigate(`/page/${pageTypeRoute}/${page.id}`); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx index ede89094d9..e3528ca1f0 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.tsx @@ -6,9 +6,8 @@ import { NewFolderButton } from './NewFolderButton'; import { NavigationResizer } from './NavigationResizer'; import { IFolder } from '../../../stores/reducers/folders/slice'; import { IPage } from '../../../stores/reducers/pages/slice'; -import { useNavigate } from 'react-router-dom'; +import { useLocation, useNavigate } from 'react-router-dom'; import React, { useEffect, useRef, useState } from 'react'; -import { useDispatch } from 'react-redux'; import { useAppSelector } from '../../../stores/store'; import { ANIMATION_DURATION, @@ -34,12 +33,19 @@ export const NavigationPanel = ({ onPageClick: (page: IPage) => void; }) => { const el = useRef(null); - const dispatch = useDispatch(); const foldersStore = useAppSelector((state) => state.folders); const pagesStore = useAppSelector((state) => state.pages); - const activePageId = useAppSelector((state) => state.activePageId); + const [activePageId, setActivePageId] = useState(''); + const currentLocation = useLocation(); const [maxHeight, setMaxHeight] = useState(0); + useEffect(() => { + const { pathname } = currentLocation; + const parts = pathname.split('/'); + const pageId = parts[parts.length - 1]; + setActivePageId(pageId); + }, [currentLocation]); + useEffect(() => { setTimeout(() => { if (!el.current) return; @@ -70,7 +76,7 @@ export const NavigationPanel = ({ const elHeight = el.current.getBoundingClientRect().height; const scrollTop = el.current.scrollTop; - if (scrollTop + elHeight < height) { + if (scrollTop + elHeight < height || scrollTop > height) { el.current.scrollTo({ top: height - elHeight, behavior: 'smooth' }); } }, ANIMATION_DURATION); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts index 9e608071e1..937825bbeb 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.hooks.ts @@ -1,18 +1,27 @@ import { IPage, pagesActions } from '../../../stores/reducers/pages/slice'; -import { useAppDispatch, useAppSelector } from '../../../stores/store'; -import { useState } from 'react'; +import { useAppDispatch } from '../../../stores/store'; +import { useEffect, useState } from 'react'; import { nanoid } from 'nanoid'; import { ViewBackendService } from '../../../stores/effects/folder/view/view_bd_svc'; import { useError } from '../../error/Error.hooks'; +import { useLocation } from 'react-router-dom'; export const usePageEvents = (page: IPage) => { const appDispatch = useAppDispatch(); const [showPageOptions, setShowPageOptions] = useState(false); const [showRenamePopup, setShowRenamePopup] = useState(false); - const activePageId = useAppSelector((state) => state.activePageId); + const [activePageId, setActivePageId] = useState(''); + const currentLocation = useLocation(); const viewBackendService: ViewBackendService = new ViewBackendService(page.id); const error = useError(); + useEffect(() => { + const { pathname } = currentLocation; + const parts = pathname.split('/'); + const pageId = parts[parts.length - 1]; + setActivePageId(pageId); + }, [currentLocation]); + const onPageOptionsClick = () => { setShowPageOptions(!showPageOptions); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/activePageId/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/activePageId/slice.ts deleted file mode 100644 index f6ba120d63..0000000000 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/activePageId/slice.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -export const activePageIdSlice = createSlice({ - name: 'activePageId', - initialState: '', - reducers: { - setActivePageId(state, action: PayloadAction) { - return action.payload; - }, - }, -}); - -export const activePageIdActions = activePageIdSlice.actions; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts index 1f96485938..9e476d875e 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/store.ts @@ -16,7 +16,6 @@ import { workspaceSlice } from './reducers/workspace/slice'; import { databaseSlice } from './reducers/database/slice'; import { boardSlice } from './reducers/board/slice'; import { errorSlice } from './reducers/error/slice'; -import { activePageIdSlice } from './reducers/activePageId/slice'; const listenerMiddlewareInstance = createListenerMiddleware({ onError: () => console.error, @@ -26,7 +25,6 @@ const store = configureStore({ reducer: { [foldersSlice.name]: foldersSlice.reducer, [pagesSlice.name]: pagesSlice.reducer, - [activePageIdSlice.name]: activePageIdSlice.reducer, [navigationWidthSlice.name]: navigationWidthSlice.reducer, [currentUserSlice.name]: currentUserSlice.reducer, [gridSlice.name]: gridSlice.reducer, From c80e77ab169a99d7af6ebb95acbf8c393845f486 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Sun, 12 Mar 2023 22:29:03 +0600 Subject: [PATCH 042/117] chore: get board groups and rows --- .../_shared/database-hooks/useCell.ts | 4 +- .../_shared/database-hooks/useDatabase.ts | 27 ++-- .../components/board/Board.hooks.ts | 55 -------- .../appflowy_app/components/board/Board.tsx | 31 ++--- .../components/board/BoardBlock.tsx | 30 ++--- .../components/board/BoardCard.tsx | 123 +++--------------- 6 files changed, 56 insertions(+), 214 deletions(-) delete mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/board/Board.hooks.ts diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts index 57082f6f70..d211a8b326 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts @@ -20,9 +20,9 @@ export const useCell = (cellIdentifier: CellIdentifier, cellCache: CellCache, fi // ignore the return value, because we are using the subscription void cellController.getCellData(); - // dispose the cell controller when the component is unmounted return () => { - void cellController.dispose(); + // dispose is causing an error + // void cellController.dispose(); }; }, []); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts index b3fc047ed5..4d4d89c9c5 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts @@ -1,30 +1,26 @@ import { useEffect, useState } from 'react'; import { DatabaseController } from '../../../stores/effects/database/database_controller'; -import { - databaseActions, - DatabaseFieldMap, - IDatabaseColumn, - IDatabaseRow, -} from '../../../stores/reducers/database/slice'; -import { useAppDispatch, useAppSelector } from '../../../stores/store'; +import { databaseActions, DatabaseFieldMap, IDatabaseColumn } from '../../../stores/reducers/database/slice'; +import { useAppDispatch } from '../../../stores/store'; import loadField from './loadField'; import { FieldInfo } from '../../../stores/effects/database/field/field_controller'; import { RowInfo } from '../../../stores/effects/database/row/row_cache'; +import { ViewLayoutTypePB } from '@/services/backend'; +import { DatabaseGroupController } from '$app/stores/effects/database/group/group_controller'; -export const useDatabase = (viewId: string) => { +export const useDatabase = (viewId: string, type?: ViewLayoutTypePB) => { const dispatch = useAppDispatch(); - const databaseStore = useAppSelector((state) => state.database); - const boardStore = useAppSelector((state) => state.board); const [controller, setController] = useState(); const [rows, setRows] = useState([]); + const [groups, setGroups] = useState([]); useEffect(() => { if (!viewId.length) return; const c = new DatabaseController(viewId); setController(c); - // on unmount dispose the controller - return () => void c.dispose(); + // dispose is causing an error + // return () => void c.dispose(); }, [viewId]); const loadFields = async (fieldInfos: readonly FieldInfo[]) => { @@ -45,7 +41,6 @@ export const useDatabase = (viewId: string) => { dispatch(databaseActions.updateFields({ fields })); dispatch(databaseActions.updateColumns({ columns })); - console.log(fields, columns); }; useEffect(() => { @@ -61,8 +56,12 @@ export const useDatabase = (viewId: string) => { }, }); await controller.open(); + + if (type === ViewLayoutTypePB.Board) { + setGroups(controller.groups.value); + } })(); }, [controller]); - return { loadFields, controller, rows }; + return { loadFields, controller, rows, groups }; }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.hooks.ts deleted file mode 100644 index f02a16d34f..0000000000 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.hooks.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { useEffect, useState } from 'react'; -import { useAppDispatch, useAppSelector } from '../../stores/store'; -import { boardActions } from '../../stores/reducers/board/slice'; -import { ISelectOption, ISelectOptionType } from '../../stores/reducers/database/slice'; - -export const useBoard = () => { - const dispatch = useAppDispatch(); - const groupingFieldId = useAppSelector((state) => state.board); - const database = useAppSelector((state) => state.database); - const [title, setTitle] = useState(''); - const [boardColumns, setBoardColumns] = useState([]); - const [movingRowId, setMovingRowId] = useState(undefined); - const [ghostLocation, setGhostLocation] = useState<{ column: number; row: number }>({ column: 0, row: 0 }); - - useEffect(() => { - setTitle(database.title); - if (database.fields[groupingFieldId]) { - setBoardColumns( - (database.fields[groupingFieldId].fieldOptions as ISelectOptionType | undefined)?.selectOptions || [] - ); - } - }, [database, groupingFieldId]); - - const changeGroupingField = (fieldId: string) => { - dispatch( - boardActions.setGroupingFieldId({ - fieldId, - }) - ); - }; - - const onGhostItemMove = (columnIndex: number, rowIndex: number) => { - setGhostLocation({ column: columnIndex, row: rowIndex }); - }; - - const startMove = (rowId: string) => { - setMovingRowId(rowId); - }; - - const endMove = () => { - setMovingRowId(undefined); - }; - - return { - title, - boardColumns, - groupingFieldId, - changeGroupingField, - startMove, - endMove, - onGhostItemMove, - movingRowId, - ghostLocation, - }; -}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx index 3869138342..ccfbb1ecfe 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx @@ -2,29 +2,17 @@ import { SettingsSvg } from '../_shared/svg/SettingsSvg'; import { SearchInput } from '../_shared/SearchInput'; import { BoardBlock } from './BoardBlock'; import { NewBoardBlock } from './NewBoardBlock'; -import { useBoard } from './Board.hooks'; import { useDatabase } from '../_shared/database-hooks/useDatabase'; +import { ViewLayoutTypePB } from '@/services/backend'; export const Board = ({ viewId }: { viewId: string }) => { - const { controller, rows } = useDatabase(viewId); - - const { - title, - boardColumns, - groupingFieldId, - changeGroupingField, - startMove, - endMove, - onGhostItemMove, - movingRowId, - ghostLocation, - } = useBoard(); + const { controller, rows, groups } = useDatabase(viewId, ViewLayoutTypePB.Board); return ( <>
-
{title}
+
{'Kanban'}
@@ -37,16 +25,15 @@ export const Board = ({ viewId }: { viewId: string }) => {
{controller && - boardColumns?.map((column, index) => ( + groups && + groups.map((group, index) => ( ))} diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx index 29bc1bc2a1..633a87af3a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx @@ -3,23 +3,20 @@ import AddSvg from '../_shared/svg/AddSvg'; import { BoardCard } from './BoardCard'; import { RowInfo } from '../../stores/effects/database/row/row_cache'; import { DatabaseController } from '../../stores/effects/database/database_controller'; +import { RowPB } from '@/services/backend'; export const BoardBlock = ({ viewId, controller, title, - groupingFieldId, rows, - startMove, - endMove, + allRows, }: { viewId: string; controller: DatabaseController; title: string; - groupingFieldId: string; - rows: readonly RowInfo[]; - startMove: (id: string) => void; - endMove: () => void; + rows: RowPB[]; + allRows: readonly RowInfo[]; }) => { return (
@@ -38,17 +35,14 @@ export const BoardBlock = ({
- {rows.map((row, index) => ( - startMove(row.row.id)} - endMove={() => endMove()} - > - ))} + {rows.map((row_pb, index) => { + const row = allRows.find((r) => r.row.id === row_pb.id); + return row ? ( + + ) : ( + + ); + })}
-
- {cells.map((cell, index) => ( - - ))} -
+
console.log('on click')} + className={`relative cursor-pointer select-none rounded-lg border border-shade-6 bg-white px-3 py-2 transition-transform duration-100 hover:bg-main-selector `} + > + +
+ {cells.map((cell, index) => ( + + ))}
- {isMoving && ( -
-   -
- )} - +
); }; From 25707edbdd67f7f97d1e2dfb9f39f0ca81c1ed0c Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 13 Mar 2023 15:16:41 +0800 Subject: [PATCH 043/117] chore: set log level & remove empty line --- frontend/appflowy_tauri/src-tauri/src/init.rs | 2 +- .../flowy-database/src/services/database_view/editor_manager.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/appflowy_tauri/src-tauri/src/init.rs b/frontend/appflowy_tauri/src-tauri/src/init.rs index 98ab6d5376..a9d22eefbf 100644 --- a/frontend/appflowy_tauri/src-tauri/src/init.rs +++ b/frontend/appflowy_tauri/src-tauri/src/init.rs @@ -10,7 +10,7 @@ pub fn init_flowy_core() -> AppFlowyCore { } data_path.push("data"); - std::env::set_var("RUST_LOG", "trace"); + std::env::set_var("RUST_LOG", "debug"); let server_config = get_client_server_configuration().unwrap(); let config = AppFlowyCoreConfig::new( data_path.to_str().unwrap(), diff --git a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs index 75c00689d6..23feaf3d5c 100644 --- a/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs +++ b/frontend/rust-lib/flowy-database/src/services/database_view/editor_manager.rs @@ -66,7 +66,6 @@ impl DatabaseViews { pub async fn close(&self, view_id: &str) { if let Some(view_editor) = self.view_editors.write().await.remove(view_id) { view_editor.close().await; - } } From 34cb2b2a092186c7e770577209cb529fabc6e494 Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 13 Mar 2023 15:57:45 +0800 Subject: [PATCH 044/117] fix: create kanban board row --- .../stores/effects/database/database_bd_svc.ts | 17 +++++++++++++---- .../effects/database/group/group_controller.ts | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts index d2fc339cdc..433c6acb17 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts @@ -39,10 +39,19 @@ export class DatabaseBackendService { return FolderEventCloseView(payload); }; - createRow = async (rowId?: string, groupId?: string) => { - const payload = CreateRowPayloadPB.fromObject({ view_id: this.viewId, start_row_id: rowId ?? undefined }); - if (groupId !== undefined) { - payload.group_id = groupId; + /// Create a row in database + /// 1.The row will be the last row in database if the params is undefined + /// 2.The row will be placed after the passed-in rowId + /// 3.The row will be moved to the group with groupId. Currently, grouping is + /// only support in kanban board. + createRow = async (params?: { rowId?: string; groupId?: string }) => { + const payload = CreateRowPayloadPB.fromObject({ view_id: this.viewId }); + if (params?.rowId !== undefined) { + payload.start_row_id = params.rowId; + } + + if (params?.groupId !== undefined) { + payload.group_id = params.groupId; } return DatabaseEventCreateRow(payload); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_controller.ts index 5077c3c017..1063cd7642 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/group/group_controller.ts @@ -94,7 +94,7 @@ export class DatabaseGroupController { }; createRow = async () => { - return this.databaseBackendSvc.createRow(this.group.group_id); + return this.databaseBackendSvc.createRow({ groupId: this.group.group_id }); }; subscribe = (callbacks: GroupDataCallbacks) => { From 88e0f6a32c617b35ce75213d2dedebfe90d7a97e Mon Sep 17 00:00:00 2001 From: appflowy Date: Mon, 13 Mar 2023 16:09:11 +0800 Subject: [PATCH 045/117] fix: appflowy session name --- frontend/appflowy_tauri/src-tauri/src/init.rs | 34 +++++++++---------- frontend/rust-lib/dart-ffi/src/lib.rs | 2 +- frontend/rust-lib/flowy-core/src/lib.rs | 4 +++ 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/frontend/appflowy_tauri/src-tauri/src/init.rs b/frontend/appflowy_tauri/src-tauri/src/init.rs index a9d22eefbf..a09c80c875 100644 --- a/frontend/appflowy_tauri/src-tauri/src/init.rs +++ b/frontend/appflowy_tauri/src-tauri/src/init.rs @@ -1,22 +1,22 @@ -use flowy_core::{get_client_server_configuration, AppFlowyCore, AppFlowyCoreConfig}; +use flowy_core::{get_client_server_configuration, AppFlowyCore, AppFlowyCoreConfig, DEFAULT_NAME}; pub fn init_flowy_core() -> AppFlowyCore { - let config_json = include_str!("../tauri.conf.json"); - let config: tauri_utils::config::Config = serde_json::from_str(config_json).unwrap(); + let config_json = include_str!("../tauri.conf.json"); + let config: tauri_utils::config::Config = serde_json::from_str(config_json).unwrap(); - let mut data_path = tauri::api::path::app_local_data_dir(&config).unwrap(); - if cfg!(debug_assertions) { - data_path.push("dev"); - } - data_path.push("data"); + let mut data_path = tauri::api::path::app_local_data_dir(&config).unwrap(); + if cfg!(debug_assertions) { + data_path.push("dev"); + } + data_path.push("data"); - std::env::set_var("RUST_LOG", "debug"); - let server_config = get_client_server_configuration().unwrap(); - let config = AppFlowyCoreConfig::new( - data_path.to_str().unwrap(), - "AppFlowy".to_string(), - server_config, - ) - .log_filter("trace", vec!["appflowy_tauri".to_string()]); - AppFlowyCore::new(config) + std::env::set_var("RUST_LOG", "debug"); + let server_config = get_client_server_configuration().unwrap(); + let config = AppFlowyCoreConfig::new( + data_path.to_str().unwrap(), + DEFAULT_NAME.to_string(), + server_config, + ) + .log_filter("trace", vec!["appflowy_tauri".to_string()]); + AppFlowyCore::new(config) } diff --git a/frontend/rust-lib/dart-ffi/src/lib.rs b/frontend/rust-lib/dart-ffi/src/lib.rs index c3bd609d6d..d05c5d6445 100644 --- a/frontend/rust-lib/dart-ffi/src/lib.rs +++ b/frontend/rust-lib/dart-ffi/src/lib.rs @@ -30,7 +30,7 @@ pub extern "C" fn init_sdk(path: *mut c_char) -> i64 { let server_config = get_client_server_configuration().unwrap(); let log_crates = vec!["flowy-ffi".to_string()]; - let config = AppFlowyCoreConfig::new(path, "appflowy".to_string(), server_config) + let config = AppFlowyCoreConfig::new(path, DEFAULT_NAME.to_string(), server_config) .log_filter("info", log_crates); *APPFLOWY_CORE.write() = Some(AppFlowyCore::new(config)); diff --git a/frontend/rust-lib/flowy-core/src/lib.rs b/frontend/rust-lib/flowy-core/src/lib.rs index 08ce100d7f..0ecdc807a6 100644 --- a/frontend/rust-lib/flowy-core/src/lib.rs +++ b/frontend/rust-lib/flowy-core/src/lib.rs @@ -33,6 +33,10 @@ use user_model::UserProfile; static INIT_LOG: AtomicBool = AtomicBool::new(false); +/// This name will be used as to identify the current [AppFlowyCore] instance. +/// Don't change this. +pub const DEFAULT_NAME: &str = "appflowy"; + #[derive(Clone)] pub struct AppFlowyCoreConfig { /// Different `AppFlowyCoreConfig` instance should have different name From a66d457f10c33b9c194e3b19728a8e748afcef02 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Mon, 13 Mar 2023 17:41:51 +0600 Subject: [PATCH 046/117] chore: import beautiful dnd --- frontend/appflowy_tauri/package.json | 2 + .../appflowy_app/components/board/Board.tsx | 42 +++++++++++-------- .../components/board/BoardBlock.tsx | 9 +++- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/frontend/appflowy_tauri/package.json b/frontend/appflowy_tauri/package.json index 8ad6f3a410..4dd4a9f63b 100644 --- a/frontend/appflowy_tauri/package.json +++ b/frontend/appflowy_tauri/package.json @@ -28,6 +28,7 @@ "jest": "^29.5.0", "nanoid": "^4.0.0", "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", "react-error-boundary": "^3.1.4", "react-i18next": "^12.2.0", @@ -47,6 +48,7 @@ "@types/is-hotkey": "^0.1.7", "@types/node": "^18.7.10", "@types/react": "^18.0.15", + "@types/react-beautiful-dnd": "^13.1.3", "@types/react-dom": "^18.0.6", "@types/utf8": "^3.0.1", "@typescript-eslint/eslint-plugin": "^5.51.0", diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx index ccfbb1ecfe..569e65b551 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx @@ -4,6 +4,7 @@ import { BoardBlock } from './BoardBlock'; import { NewBoardBlock } from './NewBoardBlock'; import { useDatabase } from '../_shared/database-hooks/useDatabase'; import { ViewLayoutTypePB } from '@/services/backend'; +import { DragDropContext, Droppable } from 'react-beautiful-dnd'; export const Board = ({ viewId }: { viewId: string }) => { const { controller, rows, groups } = useDatabase(viewId, ViewLayoutTypePB.Board); @@ -22,24 +23,31 @@ export const Board = ({ viewId }: { viewId: string }) => {
-
-
- {controller && - groups && - groups.map((group, index) => ( - - ))} - - console.log('new block')}> + console.log(res)}> +
+
+ {controller && + groups && + groups.map((group, index) => ( + + {(provided, snapshot) => ( +
+ +
+ )} +
+ ))} + console.log('new block')}> +
-
+ ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx index 633a87af3a..6f23efa8c1 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx @@ -4,6 +4,7 @@ import { BoardCard } from './BoardCard'; import { RowInfo } from '../../stores/effects/database/row/row_cache'; import { DatabaseController } from '../../stores/effects/database/database_controller'; import { RowPB } from '@/services/backend'; +import { Draggable } from 'react-beautiful-dnd'; export const BoardBlock = ({ viewId, @@ -38,7 +39,13 @@ export const BoardBlock = ({ {rows.map((row_pb, index) => { const row = allRows.find((r) => r.row.id === row_pb.id); return row ? ( - + + {(provided, snapshot) => ( +
+ +
+ )} +
) : ( ); From d92c0bffd6da4d3f8b9d41df64c13c72992449a9 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Wed, 15 Mar 2023 11:18:14 +0600 Subject: [PATCH 047/117] bug: kanban new row --- .../_shared/database-hooks/useCell.ts | 2 +- .../_shared/database-hooks/useDatabase.ts | 23 +++++++++++++++++-- .../appflowy_app/components/board/Board.tsx | 3 ++- .../components/board/BoardBlock.tsx | 9 ++++++-- 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts index d211a8b326..6db19ecbbd 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts @@ -22,7 +22,7 @@ export const useCell = (cellIdentifier: CellIdentifier, cellCache: CellCache, fi return () => { // dispose is causing an error - // void cellController.dispose(); + void cellController.dispose(); }; }, []); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts index 4d4d89c9c5..66e62977b7 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts @@ -20,7 +20,7 @@ export const useDatabase = (viewId: string, type?: ViewLayoutTypePB) => { setController(c); // dispose is causing an error - // return () => void c.dispose(); + return () => void c.dispose(); }, [viewId]); const loadFields = async (fieldInfos: readonly FieldInfo[]) => { @@ -49,11 +49,15 @@ export const useDatabase = (viewId: string, type?: ViewLayoutTypePB) => { void (async () => { controller.subscribe({ onRowsChanged: (rowInfos) => { + console.log('rows changed: ', rowInfos); setRows(rowInfos); }, onFieldsChanged: (fieldInfos) => { void loadFields(fieldInfos); }, + onGroupByField: (g) => { + console.log('on group by field: ', g); + }, }); await controller.open(); @@ -63,5 +67,20 @@ export const useDatabase = (viewId: string, type?: ViewLayoutTypePB) => { })(); }, [controller]); - return { loadFields, controller, rows, groups }; + const onNewRowClick = async (index: number) => { + if (!groups) return; + if (!controller?.groups) return; + const group = groups[index]; + await group.createRow(); + + const newGroups = controller.groups.value; + + newGroups.forEach((g) => { + console.log(g.name, g.rows); + }); + + setGroups([...controller.groups.value]); + }; + + return { loadFields, controller, rows, groups, onNewRowClick }; }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx index 569e65b551..7847169ba5 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx @@ -7,7 +7,7 @@ import { ViewLayoutTypePB } from '@/services/backend'; import { DragDropContext, Droppable } from 'react-beautiful-dnd'; export const Board = ({ viewId }: { viewId: string }) => { - const { controller, rows, groups } = useDatabase(viewId, ViewLayoutTypePB.Board); + const { controller, rows, groups, onNewRowClick } = useDatabase(viewId, ViewLayoutTypePB.Board); return ( <> @@ -39,6 +39,7 @@ export const Board = ({ viewId }: { viewId: string }) => { rows={group.rows} title={group.name} allRows={rows} + onNewRowClick={() => onNewRowClick(index)} />
)} diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx index 6f23efa8c1..c1a23be4c3 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx @@ -12,12 +12,14 @@ export const BoardBlock = ({ title, rows, allRows, + onNewRowClick, }: { viewId: string; controller: DatabaseController; title: string; rows: RowPB[]; allRows: readonly RowInfo[]; + onNewRowClick: () => void; }) => { return (
@@ -39,7 +41,7 @@ export const BoardBlock = ({ {rows.map((row_pb, index) => { const row = allRows.find((r) => r.row.id === row_pb.id); return row ? ( - + {(provided, snapshot) => (
@@ -52,7 +54,10 @@ export const BoardBlock = ({ })}
-
- console.log(res)}> +
{controller && diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts index 9308ccc456..18194bff2c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_bd_svc.ts @@ -6,9 +6,11 @@ import { DatabaseEventGetGroups, DatabaseEventMoveGroup, DatabaseEventMoveGroupRow, + DatabaseEventMoveRow, DatabaseGroupIdPB, MoveGroupPayloadPB, MoveGroupRowPayloadPB, + MoveRowPayloadPB, } from '@/services/backend/events/flowy-database'; import { GetFieldPayloadPB, @@ -68,6 +70,15 @@ export class DatabaseBackendService { return DatabaseEventMoveGroupRow(payload); }; + exchangeRow = (fromRowId: string, toRowId: string) => { + const payload = MoveRowPayloadPB.fromObject({ + view_id: this.viewId, + from_row_id: fromRowId, + to_row_id: toRowId, + }); + return DatabaseEventMoveRow(payload); + }; + moveGroup = (fromGroupId: string, toGroupId: string) => { const payload = MoveGroupPayloadPB.fromObject({ view_id: this.viewId, diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts index a9bfc66d75..226e0b58f6 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts @@ -79,6 +79,11 @@ export class DatabaseController { return this.backendService.moveRow(rowId, groupId); }; + exchangeRow = async (fromRowId: string, toRowId: string) => { + await this.backendService.exchangeRow(fromRowId, toRowId); + await this.loadGroup(); + }; + moveGroup = (fromGroupId: string, toGroupId: string) => { return this.backendService.moveGroup(fromGroupId, toGroupId); }; From fa427fe6507d7896c5fb09051e061e69212bfe3a Mon Sep 17 00:00:00 2001 From: ascarbek Date: Thu, 16 Mar 2023 18:59:05 +0600 Subject: [PATCH 052/117] chore: move row into other block --- .../components/_shared/database-hooks/useDatabase.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts index 8811c92114..4322623d00 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useDatabase.ts @@ -82,12 +82,18 @@ export const useDatabase = (viewId: string, type?: ViewLayoutTypePB) => { }; const onDragEnd: OnDragEndResponder = async (result) => { + if (!controller) return; const { source, destination } = result; - // move inside the block (group) + const group = groups.find((g) => g.groupId === source.droppableId); + if (!group) return; + if (source.droppableId === destination?.droppableId) { - const group = groups.find((g) => g.groupId === source.droppableId); - if (!group || !controller) return; + // move inside the block (group) await controller.exchangeRow(group.rows[source.index].id, group.rows[destination.index].id); + } else { + // move to different block (group) + if (!destination?.droppableId) return; + await controller.moveRow(group.rows[source.index].id, destination.droppableId); } }; From 4b1f45a4be0d8549a55f6537222c56e368f37a70 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Fri, 17 Mar 2023 13:13:04 +0600 Subject: [PATCH 053/117] fix: groups observer dispose --- .../appflowy_app/stores/effects/database/database_controller.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts index 226e0b58f6..0ac8986e8d 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/database_controller.ts @@ -154,6 +154,7 @@ export class DatabaseController { this.groups.value.forEach((group) => { void group.dispose(); }); + await this.groupsObserver.unsubscribe(); await this.backendService.closeDatabase(); await this.fieldController.dispose(); await this.databaseViewCache.dispose(); From d60c39d483414f2cb6a30eea00654c8ca96408f2 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Fri, 17 Mar 2023 15:13:51 +0600 Subject: [PATCH 054/117] chore: dnd reordering --- .../appflowy_app/components/board/Board.tsx | 27 +++++------ .../components/board/BoardBlock.tsx | 38 ++++++++------- .../components/board/BoardCard.tsx | 46 +++++++++++-------- 3 files changed, 60 insertions(+), 51 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx index 9e26ab0f9a..b367dfc642 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx @@ -4,7 +4,7 @@ import { BoardBlock } from './BoardBlock'; import { NewBoardBlock } from './NewBoardBlock'; import { useDatabase } from '../_shared/database-hooks/useDatabase'; import { ViewLayoutTypePB } from '@/services/backend'; -import { DragDropContext, Droppable } from 'react-beautiful-dnd'; +import { DragDropContext } from 'react-beautiful-dnd'; export const Board = ({ viewId }: { viewId: string }) => { const { controller, rows, groups, onNewRowClick, onDragEnd } = useDatabase(viewId, ViewLayoutTypePB.Board); @@ -29,21 +29,16 @@ export const Board = ({ viewId }: { viewId: string }) => { {controller && groups && groups.map((group, index) => ( - - {(provided, snapshot) => ( -
- onNewRowClick(index)} - /> -
- )} -
+ onNewRowClick(index)} + /> ))} console.log('new block')}>
diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx index c1a23be4c3..d62ba15aa6 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx @@ -4,9 +4,10 @@ import { BoardCard } from './BoardCard'; import { RowInfo } from '../../stores/effects/database/row/row_cache'; import { DatabaseController } from '../../stores/effects/database/database_controller'; import { RowPB } from '@/services/backend'; -import { Draggable } from 'react-beautiful-dnd'; +import { Droppable } from 'react-beautiful-dnd'; export const BoardBlock = ({ + groupId, viewId, controller, title, @@ -14,6 +15,7 @@ export const BoardBlock = ({ allRows, onNewRowClick, }: { + groupId: string; viewId: string; controller: DatabaseController; title: string; @@ -37,22 +39,24 @@ export const BoardBlock = ({
-
- {rows.map((row_pb, index) => { - const row = allRows.find((r) => r.row.id === row_pb.id); - return row ? ( - - {(provided, snapshot) => ( -
- -
- )} -
- ) : ( - - ); - })} -
+ + {(provided) => ( +
+ {rows.map((row_pb, index) => { + const row = allRows.find((r) => r.row.id === row_pb.id); + return row ? ( + + ) : ( + + ); + })} +
+ )} +
-
- {cells.map((cell, index) => ( - - ))} -
-
+ + {(provided) => ( +
console.log('on click')} + className={`relative cursor-pointer select-none rounded-lg border border-shade-6 bg-white px-3 py-2 transition-transform duration-100 hover:bg-main-selector `} + > + +
+ {cells.map((cell, cellIndex) => ( + + ))} +
+
+ )} +
); }; From baa67e2aed95a694a20c3222be9e51aa450b2dfe Mon Sep 17 00:00:00 2001 From: nathan Date: Tue, 21 Mar 2023 08:18:11 +0800 Subject: [PATCH 055/117] chore: fix import references --- .../components/_shared/database-hooks/loadField.ts | 2 +- .../grid/GridTableHeader/GridTableHeader.hooks.tsx | 2 +- .../components/grid/GridTableHeader/GridTableHeader.tsx | 2 +- .../components/layout/NavigationPanel/FolderItem.hooks.ts | 2 +- .../layout/NavigationPanel/NavigationPanel.hooks.ts | 2 +- .../components/layout/NavigationPanel/PageItem.tsx | 2 +- .../components/user/application/notifications/parser.ts | 4 ++-- .../user/application/notifications/user_listener.ts | 4 ++-- .../stores/effects/database/cell/cell_bd_svc.ts | 5 ++--- .../stores/effects/database/cell/cell_observer.ts | 4 ++-- .../stores/effects/database/cell/controller_builder.ts | 2 +- .../stores/effects/database/cell/data_parser.ts | 6 ++---- .../stores/effects/database/cell/data_persistence.ts | 6 ++---- .../stores/effects/database/cell/select_option_bd_svc.ts | 4 ++-- .../stores/effects/database/view/view_row_observer.ts | 4 ++-- .../src/appflowy_app/stores/reducers/current-user/slice.ts | 2 +- .../src/appflowy_app/stores/reducers/database/slice.ts | 4 ++-- .../stores/reducers/folders/notifications/parser.ts | 4 ++-- .../src/appflowy_app/stores/reducers/grid/slice.ts | 2 +- .../src/appflowy_app/stores/reducers/pages/slice.ts | 2 +- 20 files changed, 30 insertions(+), 35 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts index 459794f455..25471b07d7 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/loadField.ts @@ -9,7 +9,7 @@ import { NumberFormat, SingleSelectTypeOptionPB, TimeFormat, -} from '../../../../services/backend'; +} from '@/services/backend'; import { makeChecklistTypeOptionContext, makeDateTypeOptionContext, diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTableHeader/GridTableHeader.hooks.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTableHeader/GridTableHeader.hooks.tsx index 46d778f0ec..d05ddaf5f3 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTableHeader/GridTableHeader.hooks.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTableHeader/GridTableHeader.hooks.tsx @@ -1,5 +1,5 @@ import { nanoid } from 'nanoid'; -import { FieldType } from '../../../../services/backend/models/flowy-database/field_entities'; +import { FieldType } from '@/services/backend/models/flowy-database/field_entities'; import { gridActions } from '../../../stores/reducers/grid/slice'; import { useAppDispatch, useAppSelector } from '../../../stores/store'; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTableHeader/GridTableHeader.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTableHeader/GridTableHeader.tsx index 084d2c5749..27c0b72a96 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTableHeader/GridTableHeader.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTableHeader/GridTableHeader.tsx @@ -7,7 +7,7 @@ import { SingleSelectTypeSvg } from '../../_shared/svg/SingleSelectTypeSvg'; import { MultiSelectTypeSvg } from '../../_shared/svg/MultiSelectTypeSvg'; import { ChecklistTypeSvg } from '../../_shared/svg/ChecklistTypeSvg'; import { UrlTypeSvg } from '../../_shared/svg/UrlTypeSvg'; -import { FieldType } from '../../../../services/backend/models/flowy-database/field_entities'; +import { FieldType } from '@/services/backend/models/flowy-database/field_entities'; export const GridTableHeader = () => { const { fields, onAddField } = useGridTableHeaderHooks(); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts index 3c38ab70cd..5c61a933ac 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/FolderItem.hooks.ts @@ -2,7 +2,7 @@ import { foldersActions, IFolder } from '../../../stores/reducers/folders/slice' import { useEffect, useState } from 'react'; import { useAppDispatch, useAppSelector } from '../../../stores/store'; import { IPage, pagesActions } from '../../../stores/reducers/pages/slice'; -import { AppPB, ViewLayoutTypePB } from '../../../../services/backend'; +import { AppPB, ViewLayoutTypePB } from '@/services/backend'; import { AppBackendService } from '../../../stores/effects/folder/app/app_bd_svc'; import { WorkspaceBackendService } from '../../../stores/effects/folder/workspace/workspace_bd_svc'; import { useError } from '../../error/Error.hooks'; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts index 1387291293..d728c1e838 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/NavigationPanel.hooks.ts @@ -1,7 +1,7 @@ import { useAppSelector } from '../../../stores/store'; import { useNavigate } from 'react-router-dom'; import { IPage } from '../../../stores/reducers/pages/slice'; -import { ViewLayoutTypePB } from '../../../../services/backend'; +import { ViewLayoutTypePB } from '@/services/backend'; import { useState } from 'react'; export const useNavigationPanelHooks = function () { diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx index 6085fb2a8c..b1736c1435 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/layout/NavigationPanel/PageItem.tsx @@ -7,7 +7,7 @@ import { IPage } from '../../../stores/reducers/pages/slice'; import { Button } from '../../_shared/Button'; import { usePageEvents } from './PageItem.hooks'; import { RenamePopup } from './RenamePopup'; -import { ViewLayoutTypePB } from '../../../../services/backend'; +import { ViewLayoutTypePB } from '@/services/backend'; import { useEffect, useRef, useState } from 'react'; import { PAGE_ITEM_HEIGHT } from '../../_shared/constants'; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/parser.ts b/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/parser.ts index 21e5bde9ff..4e3a57af4b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/parser.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/parser.ts @@ -1,5 +1,5 @@ -import { FlowyError, UserNotification } from '../../../../../services/backend'; -import { NotificationParser, OnNotificationError } from '../../../../../services/backend/notifications'; +import { FlowyError, UserNotification } from '@/services/backend'; +import { NotificationParser, OnNotificationError } from '@/services/backend/notifications'; import { Result } from 'ts-results'; declare type UserNotificationCallback = (ty: UserNotification, payload: Result) => void; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/user_listener.ts b/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/user_listener.ts index b22a285ce2..94e0043108 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/user_listener.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/user/application/notifications/user_listener.ts @@ -1,5 +1,5 @@ -import { FlowyError, UserNotification, UserProfilePB } from '../../../../../services/backend'; -import { AFNotificationObserver, OnNotificationError } from '../../../../../services/backend/notifications'; +import { FlowyError, UserNotification, UserProfilePB } from '@/services/backend'; +import { AFNotificationObserver, OnNotificationError } from '@/services/backend/notifications'; import { UserNotificationParser } from './parser'; import { Ok, Result } from 'ts-results'; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_bd_svc.ts index 03f22277bd..1b07ebfb0a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_bd_svc.ts @@ -1,6 +1,5 @@ -import { DatabaseEventGetCell, DatabaseEventUpdateCell } from '../../../../../services/backend/events/flowy-database'; -import { CellChangesetPB, CellIdPB } from '../../../../../services/backend/models/flowy-database/cell_entities'; -import { FieldType } from '../../../../../services/backend/models/flowy-database/field_entities'; +import { DatabaseEventGetCell, DatabaseEventUpdateCell } from '@/services/backend/events/flowy-database'; +import { CellChangesetPB, CellIdPB, FieldType } from '@/services/backend'; class CellIdentifier { constructor( diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts index 9aa9763a99..7796112559 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/cell_observer.ts @@ -1,7 +1,7 @@ import { Ok, Result } from 'ts-results'; -import { ChangeNotifier } from '../../../../utils/change_notifier'; +import { ChangeNotifier } from '$app/utils/change_notifier'; import { DatabaseNotificationObserver } from '../notifications/observer'; -import { DatabaseNotification, FlowyError } from '../../../../../services/backend'; +import { DatabaseNotification, FlowyError } from '@/services/backend'; type UpdateCellNotifiedValue = Result; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts index 9d66dd6ee5..7858f5a938 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/controller_builder.ts @@ -1,4 +1,4 @@ -import { DateCellDataPB, FieldType, SelectOptionCellDataPB, URLCellDataPB } from '../../../../../services/backend'; +import { DateCellDataPB, FieldType, SelectOptionCellDataPB, URLCellDataPB } from '@/services/backend'; import { CellIdentifier } from './cell_bd_svc'; import { CellController } from './cell_controller'; import { diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts index 20a7a3e68d..86b2198b4e 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_parser.ts @@ -1,10 +1,8 @@ import utf8 from 'utf8'; import { CellBackendService, CellIdentifier } from './cell_bd_svc'; -import { DateCellDataPB } from '../../../../../services/backend/models/flowy-database/date_type_option_entities'; -import { SelectOptionCellDataPB } from '../../../../../services/backend/models/flowy-database/select_type_option'; -import { URLCellDataPB } from '../../../../../services/backend/models/flowy-database/url_type_option_entities'; +import { SelectOptionCellDataPB, URLCellDataPB, DateCellDataPB } from '@/services/backend'; import { Err, None, Ok, Option, Some } from 'ts-results'; -import { Log } from '../../../../utils/log'; +import { Log } from '$app/utils/log'; abstract class CellDataParser { abstract parserData(data: Uint8Array): Option; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts index 26e0a4afb9..c6eb7288ec 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/data_persistence.ts @@ -1,10 +1,8 @@ import { Result } from 'ts-results'; -import { FlowyError } from '../../../../../services/backend/models/flowy-error'; import { CellBackendService, CellIdentifier } from './cell_bd_svc'; import { CalendarData } from './controller_builder'; -import { DateChangesetPB } from '../../../../../services/backend/models/flowy-database/date_type_option_entities'; -import { CellIdPB } from '../../../../../services/backend/models/flowy-database/cell_entities'; -import { DatabaseEventUpdateDateCell } from '../../../../../services/backend/events/flowy-database'; +import { DateChangesetPB, FlowyError, CellIdPB } from '@/services/backend'; +import { DatabaseEventUpdateDateCell } from '@/services/backend/events/flowy-database'; export abstract class CellDataPersistence { abstract save(data: D): Promise>; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts index 1ab1a61148..af4158db3b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/cell/select_option_bd_svc.ts @@ -5,13 +5,13 @@ import { SelectOptionCellChangesetPB, SelectOptionChangesetPB, SelectOptionPB, -} from '../../../../../services/backend'; +} from '@/services/backend'; import { DatabaseEventCreateSelectOption, DatabaseEventGetSelectOptionCellData, DatabaseEventUpdateSelectOption, DatabaseEventUpdateSelectOptionCell, -} from '../../../../../services/backend/events/flowy-database'; +} from '@/services/backend/events/flowy-database'; export class SelectOptionBackendService { constructor(public readonly viewId: string, public readonly fieldId: string) {} diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts index 198c86e598..b3da8cd061 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/effects/database/view/view_row_observer.ts @@ -6,8 +6,8 @@ import { ReorderSingleRowPB, RowsChangesetPB, RowsVisibilityChangesetPB, -} from '../../../../../services/backend'; -import { ChangeNotifier } from '../../../../utils/change_notifier'; +} from '@/services/backend'; +import { ChangeNotifier } from '$app/utils/change_notifier'; import { DatabaseNotificationObserver } from '../notifications/observer'; export type RowsVisibilityNotifyValue = Result; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts index 969925bdc3..4b5fbcb5ea 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/current-user/slice.ts @@ -1,6 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { nanoid } from 'nanoid'; -import { WorkspaceSettingPB } from '../../../../services/backend/models/flowy-folder/workspace'; +import { WorkspaceSettingPB } from '@/services/backend/models/flowy-folder/workspace'; export interface ICurrentUser { id?: string; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts index 005fa75781..1c4947e3cb 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/database/slice.ts @@ -1,6 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { FieldType } from '../../../../services/backend/models/flowy-database/field_entities'; -import { DateFormat, NumberFormat, SelectOptionColorPB, TimeFormat } from '../../../../services/backend'; +import { FieldType } from '@/services/backend/models/flowy-database/field_entities'; +import { DateFormat, NumberFormat, SelectOptionColorPB, TimeFormat } from '@/services/backend'; export interface ISelectOption { selectOptionId: string; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/notifications/parser.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/notifications/parser.ts index e0220a9f22..27c091458b 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/notifications/parser.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/folders/notifications/parser.ts @@ -1,5 +1,5 @@ -import { FlowyError, FolderNotification } from '../../../../../services/backend'; -import { NotificationParser, OnNotificationError } from '../../../../../services/backend/notifications'; +import { FlowyError, FolderNotification } from '@/services/backend'; +import { NotificationParser, OnNotificationError } from '@/services/backend/notifications'; import { Result } from 'ts-results'; declare type FolderNotificationCallback = (ty: FolderNotification, payload: Result) => void; diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/grid/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/grid/slice.ts index 139bd4f012..5b72e7a270 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/grid/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/grid/slice.ts @@ -1,6 +1,6 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { nanoid } from 'nanoid'; -import { FieldType } from '../../../../services/backend/models/flowy-database/field_entities'; +import { FieldType } from '@/services/backend/models/flowy-database/field_entities'; const initialState = { title: 'My plans on the week', diff --git a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts index 9c7700d11b..804038444f 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/stores/reducers/pages/slice.ts @@ -1,5 +1,5 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; -import { ViewLayoutTypePB } from '../../../../services/backend'; +import { ViewLayoutTypePB } from '@/services/backend'; export interface IPage { id: string; From 2825e194654cbb1a52ad6d43e153c8f93fdedcc4 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Tue, 21 Mar 2023 10:50:59 +0600 Subject: [PATCH 056/117] chore: initial edit board modal --- .../board/EditBoardRow/EditBoardCell.tsx | 54 +++++++++++++++++++ .../board/EditBoardRow/EditBoardRow.tsx | 41 ++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditBoardCell.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditBoardRow.tsx diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditBoardCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditBoardCell.tsx new file mode 100644 index 0000000000..be125fcea9 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditBoardCell.tsx @@ -0,0 +1,54 @@ +import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc'; +import { useCell } from '$app/components/_shared/database-hooks/useCell'; +import { CellCache } from '$app/stores/effects/database/cell/cell_cache'; +import { FieldController } from '$app/stores/effects/database/field/field_controller'; +import { FieldType, SelectOptionCellDataPB } from '@/services/backend'; +import { TextTypeSvg } from '$app/components/_shared/svg/TextTypeSvg'; +import { NumberTypeSvg } from '$app/components/_shared/svg/NumberTypeSvg'; +import { DateTypeSvg } from '$app/components/_shared/svg/DateTypeSvg'; +import { SingleSelectTypeSvg } from '$app/components/_shared/svg/SingleSelectTypeSvg'; +import { MultiSelectTypeSvg } from '$app/components/_shared/svg/MultiSelectTypeSvg'; +import { ChecklistTypeSvg } from '$app/components/_shared/svg/ChecklistTypeSvg'; +import { UrlTypeSvg } from '$app/components/_shared/svg/UrlTypeSvg'; +import { useAppSelector } from '$app/stores/store'; + +export const EditBoardCell = ({ + cellIdentifier, + cellCache, + fieldController, +}: { + cellIdentifier: CellIdentifier; + cellCache: CellCache; + fieldController: FieldController; +}) => { + const { data } = useCell(cellIdentifier, cellCache, fieldController); + const databaseStore = useAppSelector((state) => state.database); + return ( +
+
+
+ {cellIdentifier.fieldType === FieldType.RichText && } + {cellIdentifier.fieldType === FieldType.Number && } + {cellIdentifier.fieldType === FieldType.DateTime && } + {cellIdentifier.fieldType === FieldType.SingleSelect && } + {cellIdentifier.fieldType === FieldType.MultiSelect && } + {cellIdentifier.fieldType === FieldType.Checklist && } + {cellIdentifier.fieldType === FieldType.URL && } +
+ + {databaseStore.fields[cellIdentifier.fieldId].title} + +
+
+ {(cellIdentifier.fieldType === FieldType.SingleSelect || cellIdentifier.fieldType === FieldType.MultiSelect) && ( +
+ {(data as SelectOptionCellDataPB | undefined)?.select_options?.map((option, index) => ( +
{option?.name || ''}
+ )) || ''} +
+ )} + {
{data as string}
} +
+
+ ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditBoardRow.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditBoardRow.tsx new file mode 100644 index 0000000000..e6d63cf6dd --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditBoardRow.tsx @@ -0,0 +1,41 @@ +import { CloseSvg } from '$app/components/_shared/svg/CloseSvg'; +import { useRow } from '$app/components/_shared/database-hooks/useRow'; +import { DatabaseController } from '$app/stores/effects/database/database_controller'; +import { RowInfo } from '$app/stores/effects/database/row/row_cache'; +import { EditBoardCell } from '$app/components/board/EditBoardRow/EditBoardCell'; + +export const EditBoardRow = ({ + onClose, + viewId, + controller, + rowInfo, +}: { + onClose: () => void; + viewId: string; + controller: DatabaseController; + rowInfo: RowInfo; +}) => { + const { cells } = useRow(viewId, controller, rowInfo); + + return ( +
+
+
onClose()} className={'absolute top-4 right-4'}> + +
+
+ {cells.map((cell, cellIndex) => ( + + ))} +
+
+
+ ); +}; From dc97912dbad4dee82d5d30d97dcada3258ce2050 Mon Sep 17 00:00:00 2001 From: ascarbek Date: Tue, 21 Mar 2023 11:22:42 +0600 Subject: [PATCH 057/117] fix: kanban board rendering --- .../_shared/database-hooks/useCell.ts | 13 +++++---- .../appflowy_app/components/board/Board.tsx | 15 ++++++++--- .../components/board/BoardBlock.tsx | 27 +++++++++++-------- .../components/board/BoardCard.tsx | 4 ++- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts index 8f2998902d..e04f9a8fdb 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts @@ -12,14 +12,13 @@ export const useCell = (cellIdentifier: CellIdentifier, cellCache: CellCache, fi if (!cellIdentifier || !cellCache || !fieldController) return; const builder = new CellControllerBuilder(cellIdentifier, cellCache, fieldController); const cellController = builder.build(); - cellController.subscribeChanged({ - onCellChanged: (value) => { - setData(value.unwrap()); - }, - }); - // ignore the return value, because we are using the subscription - void cellController.getCellData(); + void (async () => { + const cellData = await cellController.getCellData(); + if (cellData.some) { + setData(cellData.unwrap()); + } + })(); return () => { void cellController.dispose(); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx index b367dfc642..f492e1bd16 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx @@ -5,9 +5,18 @@ import { NewBoardBlock } from './NewBoardBlock'; import { useDatabase } from '../_shared/database-hooks/useDatabase'; import { ViewLayoutTypePB } from '@/services/backend'; import { DragDropContext } from 'react-beautiful-dnd'; +import { useState } from 'react'; +import { RowInfo } from '$app/stores/effects/database/row/row_cache'; export const Board = ({ viewId }: { viewId: string }) => { const { controller, rows, groups, onNewRowClick, onDragEnd } = useDatabase(viewId, ViewLayoutTypePB.Board); + const [showBoardRow, setShowBoardRow] = useState(false); + const [boardRowInfo, setBoardRowInfo] = useState(); + + const onOpenRow = (rowInfo: RowInfo) => { + setBoardRowInfo(rowInfo); + setShowBoardRow(true); + }; return ( <> @@ -30,20 +39,20 @@ export const Board = ({ viewId }: { viewId: string }) => { groups && groups.map((group, index) => ( onNewRowClick(index)} + onOpenRow={onOpenRow} /> ))} console.log('new block')}>
+ ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx index d62ba15aa6..fa3acf65c1 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx @@ -3,31 +3,29 @@ import AddSvg from '../_shared/svg/AddSvg'; import { BoardCard } from './BoardCard'; import { RowInfo } from '../../stores/effects/database/row/row_cache'; import { DatabaseController } from '../../stores/effects/database/database_controller'; -import { RowPB } from '@/services/backend'; import { Droppable } from 'react-beautiful-dnd'; +import { DatabaseGroupController } from '$app/stores/effects/database/group/group_controller'; export const BoardBlock = ({ - groupId, viewId, controller, - title, - rows, allRows, onNewRowClick, + onOpenRow, + group, }: { - groupId: string; viewId: string; controller: DatabaseController; - title: string; - rows: RowPB[]; allRows: readonly RowInfo[]; onNewRowClick: () => void; + onOpenRow: (rowId: RowInfo) => void; + group: DatabaseGroupController; }) => { return (
- {title} + {group.name} ()
@@ -39,17 +37,24 @@ export const BoardBlock = ({
- + {(provided) => (
- {rows.map((row_pb, index) => { + {group.rows.map((row_pb, index) => { const row = allRows.find((r) => r.row.id === row_pb.id); return row ? ( - + ) : ( ); diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx index 504b9454cd..b9b22c8263 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardCard.tsx @@ -10,11 +10,13 @@ export const BoardCard = ({ viewId, controller, rowInfo, + onOpenRow, }: { index: number; viewId: string; controller: DatabaseController; rowInfo: RowInfo; + onOpenRow: (rowId: RowInfo) => void; }) => { const { cells } = useRow(viewId, controller, rowInfo); @@ -25,7 +27,7 @@ export const BoardCard = ({ ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps} - onClick={() => console.log('on click')} + onClick={() => onOpenRow(rowInfo)} className={`relative cursor-pointer select-none rounded-lg border border-shade-6 bg-white px-3 py-2 transition-transform duration-100 hover:bg-main-selector `} > + +
+ + + {showOptions && setShowOptions(!showOptions)} />} +
); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTitle/GridTitleOptionsPopup.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTitle/GridTitleOptionsPopup.tsx new file mode 100644 index 0000000000..c57962ed93 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridTitle/GridTitleOptionsPopup.tsx @@ -0,0 +1,55 @@ +import { IPopupItem, Popup } from '../../_shared/Popup'; +import { FilterSvg } from '../../_shared/svg/FilterSvg'; +import { GroupBySvg } from '../../_shared/svg/GroupBySvg'; +import { PropertiesSvg } from '../../_shared/svg/PropertiesSvg'; +import { SortSvg } from '../../_shared/svg/SortSvg'; + +export const GridTitleOptionsPopup = ({ onClose }: { onClose?: () => void }) => { + const items: IPopupItem[] = [ + { + icon: ( + + + + ), + onClick: () => { + console.log('filter'); + }, + title: 'Filter', + }, + { + icon: ( + + + + ), + onClick: () => { + console.log('sort'); + }, + title: 'Sort', + }, + { + icon: ( + + + + ), + onClick: () => { + console.log('fields'); + }, + title: 'Fields', + }, + { + icon: ( + + + + ), + onClick: () => { + console.log('group by'); + }, + title: 'Group by', + }, + ]; + return ; +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridToolbar/GridToolbar.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridToolbar/GridToolbar.tsx index ea88a4cf7b..6039a6147a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridToolbar/GridToolbar.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/grid/GridToolbar/GridToolbar.tsx @@ -1,17 +1,11 @@ import { GridAddView } from '../GridAddView/GridAddView'; import { SearchInput } from '../../_shared/SearchInput'; -import { GridSortButton } from './GridSortButton'; -import { GridFieldsButton } from './GridFieldsButton'; -import { GridFilterButton } from './GridFilterButton'; export const GridToolbar = () => { return (
- - -
); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/views/GridPage.hooks.ts b/frontend/appflowy_tauri/src/appflowy_app/views/GridPage.hooks.ts deleted file mode 100644 index 68c0f81ebd..0000000000 --- a/frontend/appflowy_tauri/src/appflowy_app/views/GridPage.hooks.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const useGrid = () => { - const loadGrid = async (id: string) => { - console.log('loading grid'); - }; - - return { - loadGrid, - }; -}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/views/GridPage.tsx b/frontend/appflowy_tauri/src/appflowy_app/views/GridPage.tsx index ce8e474e05..b4a0f4157a 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/views/GridPage.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/views/GridPage.tsx @@ -1,45 +1,22 @@ -import { GridAddView } from '../components/grid/GridAddView/GridAddView'; -import { GridTableCount } from '../components/grid/GridTableCount/GridTableCount'; -import { GridTableHeader } from '../components/grid/GridTableHeader/GridTableHeader'; -import { GridAddRow } from '../components/grid/GridTableRows/GridAddRow'; -import { GridTableRows } from '../components/grid/GridTableRows/GridTableRows'; -import { GridTitle } from '../components/grid/GridTitle/GridTitle'; -import { SearchInput } from '../components/_shared/SearchInput'; -import { GridToolbar } from '../components/grid/GridToolbar/GridToolbar'; import { useParams } from 'react-router-dom'; -import { useGrid } from './GridPage.hooks'; -import { useEffect } from 'react'; + +import { useEffect, useState } from 'react'; +import { Grid } from '../components/grid/Grid/Grid'; export const GridPage = () => { const params = useParams(); - const { loadGrid } = useGrid(); + const [viewId, setViewId] = useState(''); useEffect(() => { - void (async () => { - if (!params?.id) return; - await loadGrid(params.id); - })(); + if (params?.id?.length) { + setViewId(params.id); + // setDatabaseId('testDb'); + } }, [params]); return ( -
-

Grid

- -
- - -
- - {/* table component view with text area for td */} -
- - - -
- - -
- - +
+

Grid: {viewId}

+ {viewId?.length && }
); }; From c0c302bdfdeb8473e2cdedc8b330f158ac9981ed Mon Sep 17 00:00:00 2001 From: ascarbek Date: Wed, 22 Mar 2023 19:54:42 +0600 Subject: [PATCH 059/117] chore: add column and edit text cell --- .../_shared/database-hooks/useCell.ts | 10 ++-- .../_shared/database-hooks/useRow.ts | 11 ++++- .../components/_shared/svg/CheckboxSvg.tsx | 13 +++++ .../components/_shared/svg/EditorCheckSvg.tsx | 8 +++ .../_shared/svg/EditorUncheckSvg.tsx | 7 +++ .../appflowy_app/components/board/Board.tsx | 12 ++++- .../components/board/BoardBlock.tsx | 2 +- .../components/board/BoardTextCell.tsx | 8 ++- .../board/EditBoardRow/EditCellText.tsx | 33 +++++++++++++ ...{EditBoardCell.tsx => EditCellWrapper.tsx} | 49 +++++++++++++++---- .../{EditBoardRow.tsx => EditRow.tsx} | 26 +++++++--- 11 files changed, 155 insertions(+), 24 deletions(-) create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/CheckboxSvg.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/EditorCheckSvg.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/EditorUncheckSvg.tsx create mode 100644 frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditCellText.tsx rename frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/{EditBoardCell.tsx => EditCellWrapper.tsx} (52%) rename frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/{EditBoardRow.tsx => EditRow.tsx} (56%) diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts index e04f9a8fdb..2fde53c206 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useCell.ts @@ -4,28 +4,32 @@ import { FieldController } from '$app/stores/effects/database/field/field_contro import { CellControllerBuilder } from '$app/stores/effects/database/cell/controller_builder'; import { DateCellDataPB, SelectOptionCellDataPB, URLCellDataPB } from '$app/../services/backend'; import { useEffect, useState } from 'react'; +import { CellController } from '$app/stores/effects/database/cell/cell_controller'; export const useCell = (cellIdentifier: CellIdentifier, cellCache: CellCache, fieldController: FieldController) => { const [data, setData] = useState(); + const [cellController, setCellController] = useState>(); useEffect(() => { if (!cellIdentifier || !cellCache || !fieldController) return; const builder = new CellControllerBuilder(cellIdentifier, cellCache, fieldController); - const cellController = builder.build(); + const c = builder.build(); + setCellController(c); void (async () => { - const cellData = await cellController.getCellData(); + const cellData = await c.getCellData(); if (cellData.some) { setData(cellData.unwrap()); } })(); return () => { - void cellController.dispose(); + void c.dispose(); }; }, [cellIdentifier, cellCache, fieldController]); return { + cellController, data, }; }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts index caed55ffeb..8f634009ff 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/database-hooks/useRow.ts @@ -3,6 +3,8 @@ import { RowController } from '$app/stores/effects/database/row/row_controller'; import { RowInfo } from '$app/stores/effects/database/row/row_cache'; import { CellIdentifier } from '$app/stores/effects/database/cell/cell_bd_svc'; import { useEffect, useState } from 'react'; +import { TypeOptionController } from '$app/stores/effects/database/field/type_option/type_option_controller'; +import { None } from 'ts-results'; export const useRow = (viewId: string, databaseController: DatabaseController, rowInfo: RowInfo) => { const [cells, setCells] = useState<{ fieldId: string; cellIdentifier: CellIdentifier }[]>([]); @@ -38,7 +40,14 @@ export const useRow = (viewId: string, databaseController: DatabaseController, r })(); }, [rowController]); + const onNewColumnClick = async () => { + if (!databaseController) return; + const controller = new TypeOptionController(viewId, None); + await controller.initialize(); + }; + return { - cells: cells, + cells, + onNewColumnClick, }; }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/CheckboxSvg.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/CheckboxSvg.tsx new file mode 100644 index 0000000000..862badd2a2 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/CheckboxSvg.tsx @@ -0,0 +1,13 @@ +export const CheckboxSvg = () => { + return ( + + + + + ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/EditorCheckSvg.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/EditorCheckSvg.tsx new file mode 100644 index 0000000000..72b7f5a3eb --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/EditorCheckSvg.tsx @@ -0,0 +1,8 @@ +export const EditorCheckSvg = () => { + return ( + + + + + ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/EditorUncheckSvg.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/EditorUncheckSvg.tsx new file mode 100644 index 0000000000..7615d69a72 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/_shared/svg/EditorUncheckSvg.tsx @@ -0,0 +1,7 @@ +export const EditorUncheckSvg = () => { + return ( + + + + ); +}; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx index f492e1bd16..4a90c5f81c 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/Board.tsx @@ -7,6 +7,7 @@ import { ViewLayoutTypePB } from '@/services/backend'; import { DragDropContext } from 'react-beautiful-dnd'; import { useState } from 'react'; import { RowInfo } from '$app/stores/effects/database/row/row_cache'; +import { EditRow } from '$app/components/board/EditBoardRow/EditRow'; export const Board = ({ viewId }: { viewId: string }) => { const { controller, rows, groups, onNewRowClick, onDragEnd } = useDatabase(viewId, ViewLayoutTypePB.Board); @@ -39,7 +40,7 @@ export const Board = ({ viewId }: { viewId: string }) => { groups && groups.map((group, index) => ( {
- + {controller && showBoardRow && boardRowInfo && ( + setShowBoardRow(false)} + viewId={viewId} + controller={controller} + rowInfo={boardRowInfo} + > + )} ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx index fa3acf65c1..0a3b20e597 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardBlock.tsx @@ -51,7 +51,7 @@ export const BoardBlock = ({ viewId={viewId} controller={controller} index={index} - key={index} + key={row.row.id} rowInfo={row} onOpenRow={onOpenRow} > diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardTextCell.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardTextCell.tsx index def0f1cd3a..dd9c517dee 100644 --- a/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardTextCell.tsx +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/BoardTextCell.tsx @@ -14,5 +14,11 @@ export const BoardTextCell = ({ }) => { const { data } = useCell(cellIdentifier, cellCache, fieldController); - return
{(data as string | undefined) || ''}
; + return ( +
+ {((data as string | undefined) || '').split('\n').map((line, index) => ( +
{line}
+ ))} +
+ ); }; diff --git a/frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditCellText.tsx b/frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditCellText.tsx new file mode 100644 index 0000000000..d7813f8bb7 --- /dev/null +++ b/frontend/appflowy_tauri/src/appflowy_app/components/board/EditBoardRow/EditCellText.tsx @@ -0,0 +1,33 @@ +import { CellController } from '$app/stores/effects/database/cell/cell_controller'; +import { useEffect, useState, KeyboardEvent, useMemo } from 'react'; + +export const EditCellText = ({ data, cellController }: { data: string; cellController: CellController }) => { + const [value, setValue] = useState(''); + const [contentRows, setContentRows] = useState(1); + useEffect(() => { + setValue(data); + }, [data]); + + useEffect(() => { + setContentRows(Math.max(1, value.split('\n').length)); + }, [value]); + + const onTextFieldChange = async (v: string) => { + setValue(v); + }; + + const save = async () => { + await cellController?.saveCellData(value); + }; + + return ( +
+