mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge remote-tracking branch 'origin/feat/appflowy_tauri_3' into feat/appflowy_tauri_3
This commit is contained in:
@ -1,3 +1,3 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
tauri_build::build()
|
tauri_build::build()
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,22 @@
|
|||||||
use flowy_core::{get_client_server_configuration, AppFlowyCore, AppFlowyCoreConfig};
|
use flowy_core::{get_client_server_configuration, AppFlowyCore, AppFlowyCoreConfig};
|
||||||
|
|
||||||
pub fn init_flowy_core() -> AppFlowyCore {
|
pub fn init_flowy_core() -> AppFlowyCore {
|
||||||
let config_json = include_str!("../tauri.conf.json");
|
let config_json = include_str!("../tauri.conf.json");
|
||||||
let config: tauri_utils::config::Config = serde_json::from_str(config_json).unwrap();
|
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();
|
let mut data_path = tauri::api::path::app_local_data_dir(&config).unwrap();
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
data_path.push("dev");
|
data_path.push("dev");
|
||||||
}
|
}
|
||||||
data_path.push("data");
|
data_path.push("data");
|
||||||
|
|
||||||
let server_config = get_client_server_configuration().unwrap();
|
std::env::set_var("RUST_LOG", "debug");
|
||||||
let config = AppFlowyCoreConfig::new(
|
let server_config = get_client_server_configuration().unwrap();
|
||||||
data_path.to_str().unwrap(),
|
let config = AppFlowyCoreConfig::new(
|
||||||
"AppFlowy".to_string(),
|
data_path.to_str().unwrap(),
|
||||||
server_config,
|
"AppFlowy".to_string(),
|
||||||
)
|
server_config,
|
||||||
.log_filter("trace", vec!["appflowy_tauri".to_string()]);
|
)
|
||||||
AppFlowyCore::new(config)
|
.log_filter("trace", vec!["appflowy_tauri".to_string()]);
|
||||||
|
AppFlowyCore::new(config)
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,6 @@ impl std::convert::From<AFPluginEventResponse> for AFTauriResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||||
#[tracing::instrument(level = "trace", skip(app_handler))]
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn invoke_request(
|
pub async fn invoke_request(
|
||||||
request: AFTauriRequest,
|
request: AFTauriRequest,
|
||||||
|
@ -60,11 +60,10 @@
|
|||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
"fullscreen": false,
|
"fullscreen": false,
|
||||||
"height": 1000,
|
"height": 1200,
|
||||||
"resizable": true,
|
"resizable": true,
|
||||||
"title": "AppFlowy",
|
"title": "AppFlowy",
|
||||||
"width": 1200,
|
"width": 1200
|
||||||
"transparent": true
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ export async function assertTextCell(rowInfo: RowInfo, databaseController: Datab
|
|||||||
onCellChanged: (value) => {
|
onCellChanged: (value) => {
|
||||||
const cellContent = value.unwrap();
|
const cellContent = value.unwrap();
|
||||||
if (cellContent !== expectedContent) {
|
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 svc = new TypeOptionBackendService(viewId);
|
||||||
const typeOptionPB = await svc.getTypeOption(fieldId, fieldType).then((result) => result.unwrap());
|
const typeOptionPB = await svc.getTypeOption(fieldId, fieldType).then((result) => result.unwrap());
|
||||||
if (typeOptionPB.field.name !== expected) {
|
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 svc = new DatabaseBackendService(viewId);
|
||||||
const databasePB = await svc.openDatabase().then((result) => result.unwrap());
|
const databasePB = await svc.openDatabase().then((result) => result.unwrap());
|
||||||
if (databasePB.fields.length !== expected) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,13 @@ import TestApiButton from './TestApiButton';
|
|||||||
import {
|
import {
|
||||||
TestCreateGrid,
|
TestCreateGrid,
|
||||||
TestCreateNewField,
|
TestCreateNewField,
|
||||||
TestCreateSelectOption,
|
TestCreateRow,
|
||||||
|
TestCreateSelectOptionInCell,
|
||||||
TestDeleteField,
|
TestDeleteField,
|
||||||
|
TestDeleteRow,
|
||||||
TestEditCell,
|
TestEditCell,
|
||||||
TestEditField,
|
TestEditField,
|
||||||
|
TestGetSingleSelectFieldData,
|
||||||
} from './TestGrid';
|
} from './TestGrid';
|
||||||
|
|
||||||
export const TestAPI = () => {
|
export const TestAPI = () => {
|
||||||
@ -15,8 +18,11 @@ export const TestAPI = () => {
|
|||||||
<ul className='m-6, space-y-2'>
|
<ul className='m-6, space-y-2'>
|
||||||
<TestApiButton></TestApiButton>
|
<TestApiButton></TestApiButton>
|
||||||
<TestCreateGrid></TestCreateGrid>
|
<TestCreateGrid></TestCreateGrid>
|
||||||
|
<TestCreateRow></TestCreateRow>
|
||||||
|
<TestDeleteRow></TestDeleteRow>
|
||||||
<TestEditCell></TestEditCell>
|
<TestEditCell></TestEditCell>
|
||||||
<TestCreateSelectOption></TestCreateSelectOption>
|
<TestCreateSelectOptionInCell></TestCreateSelectOptionInCell>
|
||||||
|
<TestGetSingleSelectFieldData></TestGetSingleSelectFieldData>
|
||||||
<TestEditField></TestEditField>
|
<TestEditField></TestEditField>
|
||||||
<TestCreateNewField></TestCreateNewField>
|
<TestCreateNewField></TestCreateNewField>
|
||||||
<TestDeleteField></TestDeleteField>
|
<TestDeleteField></TestDeleteField>
|
||||||
|
@ -1,20 +1,29 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { SelectOptionCellDataPB, ViewLayoutTypePB } from '../../../services/backend';
|
import {
|
||||||
|
FieldType,
|
||||||
|
SelectOptionCellDataPB,
|
||||||
|
SingleSelectTypeOptionPB,
|
||||||
|
ViewLayoutTypePB,
|
||||||
|
} from '../../../services/backend';
|
||||||
import { Log } from '../../utils/log';
|
import { Log } from '../../utils/log';
|
||||||
import {
|
import {
|
||||||
assertFieldName,
|
assertFieldName,
|
||||||
assertNumberOfFields,
|
assertNumberOfFields,
|
||||||
|
assertNumberOfRows,
|
||||||
assertTextCell,
|
assertTextCell,
|
||||||
createTestDatabaseView,
|
createTestDatabaseView,
|
||||||
editTextCell,
|
editTextCell,
|
||||||
makeSingleSelectCellController,
|
makeSingleSelectCellController,
|
||||||
openTestDatabase,
|
openTestDatabase,
|
||||||
} from './DatabaseTestHelper';
|
} from './DatabaseTestHelper';
|
||||||
import assert from 'assert';
|
import {
|
||||||
import { SelectOptionBackendService } from '../../stores/effects/database/cell/select_option_bd_svc';
|
SelectOptionBackendService,
|
||||||
|
SelectOptionCellBackendService,
|
||||||
|
} from '../../stores/effects/database/cell/select_option_bd_svc';
|
||||||
import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller';
|
import { TypeOptionController } from '../../stores/effects/database/field/type_option/type_option_controller';
|
||||||
import { None, Some } from 'ts-results';
|
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';
|
||||||
|
import { makeSingleSelectTypeOptionContext } from '../../stores/effects/database/field/type_option/type_option_context';
|
||||||
|
|
||||||
export const TestCreateGrid = () => {
|
export const TestCreateGrid = () => {
|
||||||
async function createBuildInGrid() {
|
async function createBuildInGrid() {
|
||||||
@ -26,16 +35,17 @@ export const TestCreateGrid = () => {
|
|||||||
},
|
},
|
||||||
onRowsChanged: async (rows) => {
|
onRowsChanged: async (rows) => {
|
||||||
if (rows.length !== 3) {
|
if (rows.length !== 3) {
|
||||||
throw Error();
|
throw Error('Expected number of rows is 3, but receive ' + rows.length + view.id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onFieldsChanged: (fields) => {
|
onFieldsChanged: (fields) => {
|
||||||
if (fields.length !== 3) {
|
if (fields.length !== 3) {
|
||||||
throw Error();
|
throw Error('Expected number of fields is 3, but receive ' + fields.length);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await databaseController.open().then((result) => result.unwrap());
|
await databaseController.open().then((result) => result.unwrap());
|
||||||
|
await databaseController.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
return TestButton('Test create build-in grid', createBuildInGrid);
|
return TestButton('Test create build-in grid', createBuildInGrid);
|
||||||
@ -45,48 +55,116 @@ export const TestEditCell = () => {
|
|||||||
async function testGridRow() {
|
async function testGridRow() {
|
||||||
const view = await createTestDatabaseView(ViewLayoutTypePB.Grid);
|
const view = await createTestDatabaseView(ViewLayoutTypePB.Grid);
|
||||||
const databaseController = await openTestDatabase(view.id);
|
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());
|
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);
|
return TestButton('Test editing cell', testGridRow);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TestCreateSelectOption = () => {
|
export const TestCreateRow = () => {
|
||||||
async function testCreateOption() {
|
async function testCreateRow() {
|
||||||
const view = await createTestDatabaseView(ViewLayoutTypePB.Grid);
|
const view = await createTestDatabaseView(ViewLayoutTypePB.Grid);
|
||||||
const databaseController = await openTestDatabase(view.id);
|
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());
|
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 a select option', testCreateOption);
|
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 TestCreateSelectOptionInCell = () => {
|
||||||
|
async function testCreateOptionInCell() {
|
||||||
|
const view = await createTestDatabaseView(ViewLayoutTypePB.Grid);
|
||||||
|
const databaseController = await openTestDatabase(view.id);
|
||||||
|
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 SelectOptionCellBackendService(cellController.cellIdentifier);
|
||||||
|
await backendSvc.createOption({ name: 'option' + index });
|
||||||
|
await cellController.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await databaseController.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = () => {
|
export const TestEditField = () => {
|
||||||
@ -104,6 +182,7 @@ export const TestEditField = () => {
|
|||||||
await controller.setFieldName(newName);
|
await controller.setFieldName(newName);
|
||||||
|
|
||||||
await assertFieldName(view.id, firstFieldInfo.field.id, firstFieldInfo.field.field_type, newName);
|
await assertFieldName(view.id, firstFieldInfo.field.id, firstFieldInfo.field.field_type, newName);
|
||||||
|
await databaseController.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
return TestButton('Test edit the column name', testEditField);
|
return TestButton('Test edit the column name', testEditField);
|
||||||
@ -120,6 +199,7 @@ export const TestCreateNewField = () => {
|
|||||||
const controller = new TypeOptionController(view.id, None);
|
const controller = new TypeOptionController(view.id, None);
|
||||||
await controller.initialize();
|
await controller.initialize();
|
||||||
await assertNumberOfFields(view.id, 4);
|
await assertNumberOfFields(view.id, 4);
|
||||||
|
await databaseController.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
return TestButton('Test create a new column', testCreateNewField);
|
return TestButton('Test create a new column', testCreateNewField);
|
||||||
@ -140,6 +220,7 @@ export const TestDeleteField = () => {
|
|||||||
await assertNumberOfFields(view.id, 3);
|
await assertNumberOfFields(view.id, 3);
|
||||||
await controller.deleteField();
|
await controller.deleteField();
|
||||||
await assertNumberOfFields(view.id, 2);
|
await assertNumberOfFields(view.id, 2);
|
||||||
|
await databaseController.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
return TestButton('Test delete a new column', testDeleteField);
|
return TestButton('Test delete a new column', testDeleteField);
|
||||||
|
@ -5,32 +5,37 @@ export class CellCacheKey {
|
|||||||
constructor(public readonly fieldId: string, public readonly rowId: string) {}
|
constructor(public readonly fieldId: string, public readonly rowId: string) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CellDataByRowId = Map<string, any>;
|
||||||
|
|
||||||
export class CellCache {
|
export class CellCache {
|
||||||
_cellDataByFieldId = new Map<string, Map<string, any>>();
|
private cellDataByFieldId = new Map<string, CellDataByRowId>();
|
||||||
|
|
||||||
constructor(public readonly databaseId: string) {}
|
constructor(public readonly databaseId: string) {}
|
||||||
|
|
||||||
remove = (key: CellCacheKey) => {
|
remove = (key: CellCacheKey) => {
|
||||||
const inner = this._cellDataByFieldId.get(key.fieldId);
|
const cellDataByRowId = this.cellDataByFieldId.get(key.fieldId);
|
||||||
if (inner !== undefined) {
|
if (cellDataByRowId !== undefined) {
|
||||||
inner.delete(key.rowId);
|
cellDataByRowId.delete(key.rowId);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
removeWithFieldId = (fieldId: string) => {
|
removeWithFieldId = (fieldId: string) => {
|
||||||
this._cellDataByFieldId.delete(fieldId);
|
this.cellDataByFieldId.delete(fieldId);
|
||||||
};
|
};
|
||||||
|
|
||||||
insert = (key: CellCacheKey, value: any) => {
|
insert = (key: CellCacheKey, value: any) => {
|
||||||
let inner = this._cellDataByFieldId.get(key.fieldId);
|
const cellDataByRowId = this.cellDataByFieldId.get(key.fieldId);
|
||||||
if (inner === undefined) {
|
if (cellDataByRowId === undefined) {
|
||||||
inner = this._cellDataByFieldId.set(key.fieldId, new Map());
|
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<T>(key: CellCacheKey): Option<T> {
|
get<T>(key: CellCacheKey): Option<T> {
|
||||||
const inner = this._cellDataByFieldId.get(key.fieldId);
|
const inner = this.cellDataByFieldId.get(key.fieldId);
|
||||||
if (inner === undefined) {
|
if (inner === undefined) {
|
||||||
return None;
|
return None;
|
||||||
} else {
|
} else {
|
||||||
|
@ -14,10 +14,10 @@ export abstract class CellFieldNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class CellController<T, D> {
|
export class CellController<T, D> {
|
||||||
private _fieldBackendService: FieldBackendService;
|
private fieldBackendService: FieldBackendService;
|
||||||
private _cellDataNotifier: CellDataNotifier<Option<T>>;
|
private cellDataNotifier: CellDataNotifier<Option<T>>;
|
||||||
private _cellObserver: CellObserver;
|
private cellObserver: CellObserver;
|
||||||
private _cacheKey: CellCacheKey;
|
private readonly cacheKey: CellCacheKey;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public readonly cellIdentifier: CellIdentifier,
|
public readonly cellIdentifier: CellIdentifier,
|
||||||
@ -26,17 +26,17 @@ export class CellController<T, D> {
|
|||||||
private readonly cellDataLoader: CellDataLoader<T>,
|
private readonly cellDataLoader: CellDataLoader<T>,
|
||||||
private readonly cellDataPersistence: CellDataPersistence<D>
|
private readonly cellDataPersistence: CellDataPersistence<D>
|
||||||
) {
|
) {
|
||||||
this._fieldBackendService = new FieldBackendService(cellIdentifier.viewId, cellIdentifier.fieldId);
|
this.fieldBackendService = new FieldBackendService(cellIdentifier.viewId, cellIdentifier.fieldId);
|
||||||
this._cacheKey = new CellCacheKey(cellIdentifier.rowId, cellIdentifier.fieldId);
|
this.cacheKey = new CellCacheKey(cellIdentifier.rowId, cellIdentifier.fieldId);
|
||||||
this._cellDataNotifier = new CellDataNotifier(cellCache.get<T>(this._cacheKey));
|
this.cellDataNotifier = new CellDataNotifier(cellCache.get<T>(this.cacheKey));
|
||||||
this._cellObserver = new CellObserver(cellIdentifier.rowId, cellIdentifier.fieldId);
|
this.cellObserver = new CellObserver(cellIdentifier.rowId, cellIdentifier.fieldId);
|
||||||
this._cellObserver.subscribe({
|
void this.cellObserver.subscribe({
|
||||||
/// 1.Listen on user edit event and load the new cell data if needed.
|
/// 1.Listen on user edit event and load the new cell data if needed.
|
||||||
/// For example:
|
/// For example:
|
||||||
/// user input: 12
|
/// user input: 12
|
||||||
/// cell display: $12
|
/// cell display: $12
|
||||||
onCellChanged: async () => {
|
onCellChanged: async () => {
|
||||||
this.cellCache.remove(this._cacheKey);
|
this.cellCache.remove(this.cacheKey);
|
||||||
await this._loadCellData();
|
await this._loadCellData();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -55,7 +55,7 @@ export class CellController<T, D> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this._cellDataNotifier.observer.subscribe((cellData) => {
|
this.cellDataNotifier.observer.subscribe((cellData) => {
|
||||||
if (cellData !== null) {
|
if (cellData !== null) {
|
||||||
callbacks.onCellChanged(cellData);
|
callbacks.onCellChanged(cellData);
|
||||||
}
|
}
|
||||||
@ -63,7 +63,7 @@ export class CellController<T, D> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getTypeOption = async <P extends TypeOptionParser<PD>, PD>(parser: P) => {
|
getTypeOption = async <P extends TypeOptionParser<PD>, PD>(parser: P) => {
|
||||||
const result = await this._fieldBackendService.getTypeOptionData(this.cellIdentifier.fieldType);
|
const result = await this.fieldBackendService.getTypeOptionData(this.cellIdentifier.fieldType);
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
return Ok(parser.fromBuffer(result.val.type_option_data));
|
return Ok(parser.fromBuffer(result.val.type_option_data));
|
||||||
} else {
|
} else {
|
||||||
@ -83,7 +83,7 @@ export class CellController<T, D> {
|
|||||||
/// data from the backend and then the [onCellChanged] will
|
/// data from the backend and then the [onCellChanged] will
|
||||||
/// get called
|
/// get called
|
||||||
getCellData = (): Option<T> => {
|
getCellData = (): Option<T> => {
|
||||||
const cellData = this.cellCache.get<T>(this._cacheKey);
|
const cellData = this.cellCache.get<T>(this.cacheKey);
|
||||||
if (cellData.none) {
|
if (cellData.none) {
|
||||||
void this._loadCellData();
|
void this._loadCellData();
|
||||||
}
|
}
|
||||||
@ -93,14 +93,18 @@ export class CellController<T, D> {
|
|||||||
private _loadCellData = () => {
|
private _loadCellData = () => {
|
||||||
return this.cellDataLoader.loadData().then((result) => {
|
return this.cellDataLoader.loadData().then((result) => {
|
||||||
if (result.ok && result.val !== undefined) {
|
if (result.ok && result.val !== undefined) {
|
||||||
this.cellCache.insert(this._cacheKey, result.val);
|
this.cellCache.insert(this.cacheKey, result.val);
|
||||||
this._cellDataNotifier.cellData = Some(result.val);
|
this.cellDataNotifier.cellData = Some(result.val);
|
||||||
} else {
|
} else {
|
||||||
this.cellCache.remove(this._cacheKey);
|
this.cellCache.remove(this.cacheKey);
|
||||||
this._cellDataNotifier.cellData = None;
|
this.cellDataNotifier.cellData = None;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dispose = async () => {
|
||||||
|
await this.cellObserver.unsubscribe();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CellFieldNotifierImpl extends CellFieldNotifier {
|
export class CellFieldNotifierImpl extends CellFieldNotifier {
|
||||||
|
@ -13,7 +13,7 @@ export class CellObserver {
|
|||||||
|
|
||||||
constructor(public readonly rowId: string, public readonly fieldId: string) {}
|
constructor(public readonly rowId: string, public readonly fieldId: string) {}
|
||||||
|
|
||||||
subscribe = (callbacks: { onCellChanged: CellChangedCallback }) => {
|
subscribe = async (callbacks: { onCellChanged: CellChangedCallback }) => {
|
||||||
this._notifier = new ChangeNotifier();
|
this._notifier = new ChangeNotifier();
|
||||||
this._notifier?.observer.subscribe(callbacks.onCellChanged);
|
this._notifier?.observer.subscribe(callbacks.onCellChanged);
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ export class CellObserver {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return undefined;
|
await this._listener.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
unsubscribe = async () => {
|
unsubscribe = async () => {
|
||||||
|
@ -14,6 +14,20 @@ import {
|
|||||||
} from '../../../../../services/backend/events/flowy-database';
|
} from '../../../../../services/backend/events/flowy-database';
|
||||||
|
|
||||||
export class SelectOptionBackendService {
|
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) {}
|
constructor(public readonly cellIdentifier: CellIdentifier) {}
|
||||||
|
|
||||||
createOption = async (params: { name: string; isSelect?: boolean }) => {
|
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) => {
|
updateOption = (option: SelectOptionPB) => {
|
||||||
const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() });
|
const payload = SelectOptionChangesetPB.fromObject({ cell_identifier: this._cellIdentifier() });
|
||||||
payload.update_options.push(option);
|
payload.update_options.push(option);
|
||||||
@ -59,16 +83,6 @@ export class SelectOptionBackendService {
|
|||||||
return DatabaseEventUpdateSelectOptionCell(payload);
|
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 = () => {
|
private _cellIdentifier = () => {
|
||||||
return CellIdPB.fromObject({
|
return CellIdPB.fromObject({
|
||||||
view_id: this.cellIdentifier.viewId,
|
view_id: this.cellIdentifier.viewId,
|
||||||
|
@ -33,8 +33,7 @@ export class DatabaseBackendService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
createRow = async (rowId?: string) => {
|
createRow = async (rowId?: string) => {
|
||||||
const props = { database_id: this.viewId, start_row_id: rowId ?? undefined };
|
const payload = CreateRowPayloadPB.fromObject({ view_id: this.viewId, start_row_id: rowId ?? undefined });
|
||||||
const payload = CreateRowPayloadPB.fromObject(props);
|
|
||||||
return DatabaseEventCreateRow(payload);
|
return DatabaseEventCreateRow(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,13 +12,13 @@ export type SubscribeCallback = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export class DatabaseController {
|
export class DatabaseController {
|
||||||
private _backendService: DatabaseBackendService;
|
private backendService: DatabaseBackendService;
|
||||||
fieldController: FieldController;
|
fieldController: FieldController;
|
||||||
databaseViewCache: DatabaseViewCache;
|
databaseViewCache: DatabaseViewCache;
|
||||||
private _callback?: SubscribeCallback;
|
private _callback?: SubscribeCallback;
|
||||||
|
|
||||||
constructor(public readonly viewId: string) {
|
constructor(public readonly viewId: string) {
|
||||||
this._backendService = new DatabaseBackendService(viewId);
|
this.backendService = new DatabaseBackendService(viewId);
|
||||||
this.fieldController = new FieldController(viewId);
|
this.fieldController = new FieldController(viewId);
|
||||||
this.databaseViewCache = new DatabaseViewCache(viewId, this.fieldController);
|
this.databaseViewCache = new DatabaseViewCache(viewId, this.fieldController);
|
||||||
}
|
}
|
||||||
@ -32,11 +32,13 @@ export class DatabaseController {
|
|||||||
};
|
};
|
||||||
|
|
||||||
open = async () => {
|
open = async () => {
|
||||||
const result = await this._backendService.openDatabase();
|
const result = await this.backendService.openDatabase();
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
const database: DatabasePB = result.val;
|
const database: DatabasePB = result.val;
|
||||||
this._callback?.onViewChanged?.(database);
|
this._callback?.onViewChanged?.(database);
|
||||||
await this.fieldController.loadFields(database.fields);
|
await this.fieldController.loadFields(database.fields);
|
||||||
|
await this.databaseViewCache.listenOnRowsChanged();
|
||||||
|
await this.fieldController.listenOnFieldChanges();
|
||||||
this.databaseViewCache.initializeWithRows(database.rows);
|
this.databaseViewCache.initializeWithRows(database.rows);
|
||||||
return Ok.EMPTY;
|
return Ok.EMPTY;
|
||||||
} else {
|
} else {
|
||||||
@ -45,11 +47,11 @@ export class DatabaseController {
|
|||||||
};
|
};
|
||||||
|
|
||||||
createRow = async () => {
|
createRow = async () => {
|
||||||
return this._backendService.createRow();
|
return this.backendService.createRow();
|
||||||
};
|
};
|
||||||
|
|
||||||
dispose = async () => {
|
dispose = async () => {
|
||||||
await this._backendService.closeDatabase();
|
await this.backendService.closeDatabase();
|
||||||
await this.fieldController.dispose();
|
await this.fieldController.dispose();
|
||||||
await this.databaseViewCache.dispose();
|
await this.databaseViewCache.dispose();
|
||||||
};
|
};
|
||||||
|
@ -5,47 +5,45 @@ import { FieldIdPB, FieldPB, IndexFieldPB } from '../../../../../services/backen
|
|||||||
import { ChangeNotifier } from '../../../../utils/change_notifier';
|
import { ChangeNotifier } from '../../../../utils/change_notifier';
|
||||||
|
|
||||||
export class FieldController {
|
export class FieldController {
|
||||||
private _fieldListener: DatabaseFieldChangesetObserver;
|
private fieldListener: DatabaseFieldChangesetObserver;
|
||||||
private _backendService: DatabaseBackendService;
|
private backendService: DatabaseBackendService;
|
||||||
private _fieldNotifier = new FieldNotifier([]);
|
private fieldNotifier = new FieldNotifier([]);
|
||||||
|
|
||||||
constructor(public readonly viewId: string) {
|
constructor(public readonly viewId: string) {
|
||||||
this._backendService = new DatabaseBackendService(viewId);
|
this.backendService = new DatabaseBackendService(viewId);
|
||||||
this._fieldListener = new DatabaseFieldChangesetObserver(viewId);
|
this.fieldListener = new DatabaseFieldChangesetObserver(viewId);
|
||||||
|
|
||||||
this._listenOnFieldChanges();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose = async () => {
|
dispose = async () => {
|
||||||
this._fieldNotifier.unsubscribe();
|
this.fieldNotifier.unsubscribe();
|
||||||
await this._fieldListener.unsubscribe();
|
await this.fieldListener.unsubscribe();
|
||||||
};
|
};
|
||||||
|
|
||||||
get fieldInfos(): readonly FieldInfo[] {
|
get fieldInfos(): readonly FieldInfo[] {
|
||||||
return this._fieldNotifier.fieldInfos;
|
return this.fieldNotifier.fieldInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
getField = (fieldId: string): FieldInfo | undefined => {
|
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[]) => {
|
loadFields = async (fieldIds: FieldIdPB[]) => {
|
||||||
const result = await this._backendService.getFields(fieldIds);
|
const result = await this.backendService.getFields(fieldIds);
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._fieldNotifier.fieldInfos = result.val.map((field) => new FieldInfo(field));
|
this.fieldNotifier.fieldInfos = result.val.map((field) => new FieldInfo(field));
|
||||||
} else {
|
} else {
|
||||||
Log.error(result.val);
|
Log.error(result.val);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
subscribeOnFieldsChanged = (callback?: (fieldInfos: readonly FieldInfo[]) => void) => {
|
subscribeOnFieldsChanged = (callback?: (fieldInfos: readonly FieldInfo[]) => void) => {
|
||||||
return this._fieldNotifier.observer.subscribe((fieldInfos) => {
|
return this.fieldNotifier.observer.subscribe((fieldInfos) => {
|
||||||
callback?.(fieldInfos);
|
callback?.(fieldInfos);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
_listenOnFieldChanges = () => {
|
listenOnFieldChanges = async () => {
|
||||||
this._fieldListener.subscribe({
|
await this.fieldListener.subscribe({
|
||||||
onFieldsChanged: (result) => {
|
onFieldsChanged: (result) => {
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
const changeset = result.val;
|
const changeset = result.val;
|
||||||
@ -70,7 +68,7 @@ export class FieldController {
|
|||||||
};
|
};
|
||||||
const newFieldInfos = [...this.fieldInfos];
|
const newFieldInfos = [...this.fieldInfos];
|
||||||
newFieldInfos.filter(predicate);
|
newFieldInfos.filter(predicate);
|
||||||
this._fieldNotifier.fieldInfos = newFieldInfos;
|
this.fieldNotifier.fieldInfos = newFieldInfos;
|
||||||
};
|
};
|
||||||
|
|
||||||
_insertFields = (insertedFields: IndexFieldPB[]) => {
|
_insertFields = (insertedFields: IndexFieldPB[]) => {
|
||||||
@ -86,7 +84,7 @@ export class FieldController {
|
|||||||
newFieldInfos.push(fieldInfo);
|
newFieldInfos.push(fieldInfo);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this._fieldNotifier.fieldInfos = newFieldInfos;
|
this.fieldNotifier.fieldInfos = newFieldInfos;
|
||||||
};
|
};
|
||||||
|
|
||||||
_updateFields = (updatedFields: FieldPB[]) => {
|
_updateFields = (updatedFields: FieldPB[]) => {
|
||||||
@ -104,7 +102,7 @@ export class FieldController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this._fieldNotifier.fieldInfos = newFieldInfos;
|
this.fieldNotifier.fieldInfos = newFieldInfos;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,24 +7,24 @@ type UpdateFieldNotifiedValue = Result<DatabaseFieldChangesetPB, FlowyError>;
|
|||||||
export type DatabaseNotificationCallback = (value: UpdateFieldNotifiedValue) => void;
|
export type DatabaseNotificationCallback = (value: UpdateFieldNotifiedValue) => void;
|
||||||
|
|
||||||
export class DatabaseFieldChangesetObserver {
|
export class DatabaseFieldChangesetObserver {
|
||||||
private _notifier?: ChangeNotifier<UpdateFieldNotifiedValue>;
|
private notifier?: ChangeNotifier<UpdateFieldNotifiedValue>;
|
||||||
private _listener?: DatabaseNotificationObserver;
|
private listener?: DatabaseNotificationObserver;
|
||||||
|
|
||||||
constructor(public readonly viewId: string) {}
|
constructor(public readonly viewId: string) {}
|
||||||
|
|
||||||
subscribe = (callbacks: { onFieldsChanged: DatabaseNotificationCallback }) => {
|
subscribe = async (callbacks: { onFieldsChanged: DatabaseNotificationCallback }) => {
|
||||||
this._notifier = new ChangeNotifier();
|
this.notifier = new ChangeNotifier();
|
||||||
this._notifier?.observer.subscribe(callbacks.onFieldsChanged);
|
this.notifier?.observer.subscribe(callbacks.onFieldsChanged);
|
||||||
|
|
||||||
this._listener = new DatabaseNotificationObserver({
|
this.listener = new DatabaseNotificationObserver({
|
||||||
viewId: this.viewId,
|
viewId: this.viewId,
|
||||||
parserHandler: (notification, result) => {
|
parserHandler: (notification, result) => {
|
||||||
switch (notification) {
|
switch (notification) {
|
||||||
case DatabaseNotification.DidUpdateFields:
|
case DatabaseNotification.DidUpdateFields:
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._notifier?.notify(Ok(DatabaseFieldChangesetPB.deserializeBinary(result.val)));
|
this.notifier?.notify(Ok(DatabaseFieldChangesetPB.deserializeBinary(result.val)));
|
||||||
} else {
|
} else {
|
||||||
this._notifier?.notify(result);
|
this.notifier?.notify(result);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
@ -32,12 +32,12 @@ export class DatabaseFieldChangesetObserver {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return undefined;
|
await this.listener.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
unsubscribe = async () => {
|
unsubscribe = async () => {
|
||||||
this._notifier?.unsubscribe();
|
this.notifier?.unsubscribe();
|
||||||
await this._listener?.stop();
|
await this.listener?.stop();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ export class DatabaseFieldObserver {
|
|||||||
|
|
||||||
constructor(public readonly fieldId: string) {}
|
constructor(public readonly fieldId: string) {}
|
||||||
|
|
||||||
subscribe = (callbacks: { onFieldsChanged: FieldNotificationCallback }) => {
|
subscribe = async (callbacks: { onFieldsChanged: FieldNotificationCallback }) => {
|
||||||
this._notifier = new ChangeNotifier();
|
this._notifier = new ChangeNotifier();
|
||||||
this._notifier?.observer.subscribe(callbacks.onFieldsChanged);
|
this._notifier?.observer.subscribe(callbacks.onFieldsChanged);
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ export class DatabaseFieldObserver {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return undefined;
|
await this._listener.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
unsubscribe = async () => {
|
unsubscribe = async () => {
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
URLTypeOptionPB,
|
URLTypeOptionPB,
|
||||||
} from '../../../../../../services/backend';
|
} from '../../../../../../services/backend';
|
||||||
import { utf8Decoder, utf8Encoder } from '../../cell/data_parser';
|
import { utf8Decoder, utf8Encoder } from '../../cell/data_parser';
|
||||||
|
import { DatabaseFieldObserver } from '../field_observer';
|
||||||
|
|
||||||
abstract class TypeOptionSerde<T> {
|
abstract class TypeOptionSerde<T> {
|
||||||
abstract deserialize(buffer: Uint8Array): T;
|
abstract deserialize(buffer: Uint8Array): T;
|
||||||
@ -164,9 +165,17 @@ class ChecklistTypeOptionSerde extends TypeOptionSerde<ChecklistTypeOptionPB> {
|
|||||||
|
|
||||||
export class TypeOptionContext<T> {
|
export class TypeOptionContext<T> {
|
||||||
private typeOption: Option<T>;
|
private typeOption: Option<T>;
|
||||||
|
private fieldObserver: DatabaseFieldObserver;
|
||||||
|
|
||||||
constructor(public readonly parser: TypeOptionSerde<T>, private readonly controller: TypeOptionController) {
|
constructor(public readonly parser: TypeOptionSerde<T>, private readonly controller: TypeOptionController) {
|
||||||
this.typeOption = None;
|
this.typeOption = None;
|
||||||
|
this.fieldObserver = new DatabaseFieldObserver(controller.fieldId);
|
||||||
|
|
||||||
|
void this.fieldObserver.subscribe({
|
||||||
|
onFieldsChanged: () => {
|
||||||
|
void this.getTypeOption();
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get viewId(): string {
|
get viewId(): string {
|
||||||
@ -174,20 +183,23 @@ export class TypeOptionContext<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTypeOption = async (): Promise<Result<T, FlowyError>> => {
|
getTypeOption = async (): Promise<Result<T, FlowyError>> => {
|
||||||
if (this.typeOption.some) {
|
|
||||||
return Ok(this.typeOption.val);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await this.controller.getTypeOption();
|
const result = await this.controller.getTypeOption();
|
||||||
if (result.ok) {
|
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 {
|
} else {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setTypeOption = (typeOption: T) => {
|
// Save the typeOption to disk
|
||||||
this.controller.typeOption = this.parser.serialize(typeOption);
|
setTypeOption = async (typeOption: T) => {
|
||||||
|
await this.controller.saveTypeOption(this.parser.serialize(typeOption));
|
||||||
this.typeOption = Some(typeOption);
|
this.typeOption = Some(typeOption);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dispose = async () => {
|
||||||
|
await this.fieldObserver.unsubscribe();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -59,10 +59,10 @@ export class TypeOptionController {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
set typeOption(data: Uint8Array) {
|
saveTypeOption = async (data: Uint8Array) => {
|
||||||
if (this.typeOptionData.some) {
|
if (this.typeOptionData.some) {
|
||||||
this.typeOptionData.val.type_option_data = data;
|
this.typeOptionData.val.type_option_data = data;
|
||||||
void this.fieldBackendSvc?.updateTypeOption(data).then((result) => {
|
await this.fieldBackendSvc?.updateTypeOption(data).then((result) => {
|
||||||
if (result.err) {
|
if (result.err) {
|
||||||
Log.error(result.val);
|
Log.error(result.val);
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ export class TypeOptionController {
|
|||||||
} else {
|
} else {
|
||||||
throw Error('Unexpect empty type option data. Should call initialize first');
|
throw Error('Unexpect empty type option data. Should call initialize first');
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
deleteField = async () => {
|
deleteField = async () => {
|
||||||
if (this.fieldBackendSvc === undefined) {
|
if (this.fieldBackendSvc === undefined) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { DatabaseNotification } from '../../../../../services/backend';
|
import { DatabaseNotification, FlowyError } from '../../../../../services/backend';
|
||||||
import { AFNotificationObserver } from '../../../../../services/backend/notifications';
|
import { AFNotificationObserver } from '../../../../../services/backend/notifications';
|
||||||
import { DatabaseNotificationParser } from './parser';
|
import { DatabaseNotificationParser } from './parser';
|
||||||
import { FlowyError } from '../../../../../services/backend';
|
|
||||||
import { Result } from 'ts-results';
|
import { Result } from 'ts-results';
|
||||||
|
|
||||||
export type ParserHandler = (notification: DatabaseNotification, result: Result<Uint8Array, FlowyError>) => void;
|
export type ParserHandler = (notification: DatabaseNotification, result: Result<Uint8Array, FlowyError>) => void;
|
||||||
|
@ -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);
|
||||||
|
};
|
||||||
|
}
|
@ -1,63 +1,62 @@
|
|||||||
import { DatabaseViewRowsObserver } from './view_row_observer';
|
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 { FieldController } from '../field/field_controller';
|
||||||
import { RowPB } from '../../../../../services/backend/models/flowy-database/row_entities';
|
import { RowPB } from '../../../../../services/backend';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
export class DatabaseViewCache {
|
export class DatabaseViewCache {
|
||||||
private readonly _rowsObserver: DatabaseViewRowsObserver;
|
private readonly rowsObserver: DatabaseViewRowsObserver;
|
||||||
private readonly _rowCache: RowCache;
|
private readonly rowCache: RowCache;
|
||||||
private readonly _fieldSubscription?: Subscription;
|
private readonly fieldSubscription?: Subscription;
|
||||||
|
|
||||||
constructor(public readonly viewId: string, fieldController: FieldController) {
|
constructor(public readonly viewId: string, fieldController: FieldController) {
|
||||||
this._rowsObserver = new DatabaseViewRowsObserver(viewId);
|
this.rowsObserver = new DatabaseViewRowsObserver(viewId);
|
||||||
this._rowCache = new RowCache(viewId, () => fieldController.fieldInfos);
|
this.rowCache = new RowCache(viewId, () => fieldController.fieldInfos);
|
||||||
this._fieldSubscription = fieldController.subscribeOnFieldsChanged((fieldInfos) => {
|
this.fieldSubscription = fieldController.subscribeOnFieldsChanged((fieldInfos) => {
|
||||||
fieldInfos.forEach((fieldInfo) => {
|
fieldInfos.forEach((fieldInfo) => {
|
||||||
this._rowCache.onFieldUpdated(fieldInfo);
|
this.rowCache.onFieldUpdated(fieldInfo);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this._listenOnRowsChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initializeWithRows = (rows: RowPB[]) => {
|
initializeWithRows = (rows: RowPB[]) => {
|
||||||
this._rowCache.initializeRows(rows);
|
this.rowCache.initializeRows(rows);
|
||||||
};
|
};
|
||||||
|
|
||||||
get rowInfos(): readonly RowInfo[] {
|
get rowInfos(): readonly RowInfo[] {
|
||||||
return this._rowCache.rows;
|
return this.rowCache.rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
getRowCache = () => {
|
getRowCache = () => {
|
||||||
return this._rowCache;
|
return this.rowCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
dispose = async () => {
|
dispose = async () => {
|
||||||
this._fieldSubscription?.unsubscribe();
|
this.fieldSubscription?.unsubscribe();
|
||||||
await this._rowsObserver.unsubscribe();
|
await this.rowsObserver.unsubscribe();
|
||||||
await this._rowCache.dispose();
|
await this.rowCache.dispose();
|
||||||
};
|
};
|
||||||
|
|
||||||
_listenOnRowsChanged = () => {
|
listenOnRowsChanged = async () => {
|
||||||
this._rowsObserver.subscribe({
|
await this.rowsObserver.subscribe({
|
||||||
onRowsVisibilityChanged: (result) => {
|
onRowsVisibilityChanged: (result) => {
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._rowCache.applyRowsVisibility(result.val);
|
this.rowCache.applyRowsVisibility(result.val);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onNumberOfRowsChanged: (result) => {
|
onNumberOfRowsChanged: (result) => {
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._rowCache.applyRowsChanged(result.val);
|
this.rowCache.applyRowsChanged(result.val);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onReorderRows: (result) => {
|
onReorderRows: (result) => {
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._rowCache.applyReorderRows(result.val);
|
this.rowCache.applyReorderRows(result.val);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onReorderSingleRow: (result) => {
|
onReorderSingleRow: (result) => {
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._rowCache.applyReorderSingleRow(result.val);
|
this.rowCache.applyReorderSingleRow(result.val);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -16,26 +16,26 @@ export type ReorderRowsNotifyValue = Result<string[], FlowyError>;
|
|||||||
export type ReorderSingleRowNotifyValue = Result<ReorderSingleRowPB, FlowyError>;
|
export type ReorderSingleRowNotifyValue = Result<ReorderSingleRowPB, FlowyError>;
|
||||||
|
|
||||||
export class DatabaseViewRowsObserver {
|
export class DatabaseViewRowsObserver {
|
||||||
private _rowsVisibilityNotifier = new ChangeNotifier<RowsVisibilityNotifyValue>();
|
private rowsVisibilityNotifier = new ChangeNotifier<RowsVisibilityNotifyValue>();
|
||||||
private _rowsNotifier = new ChangeNotifier<RowsNotifyValue>();
|
private rowsNotifier = new ChangeNotifier<RowsNotifyValue>();
|
||||||
private _reorderRowsNotifier = new ChangeNotifier<ReorderRowsNotifyValue>();
|
private reorderRowsNotifier = new ChangeNotifier<ReorderRowsNotifyValue>();
|
||||||
private _reorderSingleRowNotifier = new ChangeNotifier<ReorderSingleRowNotifyValue>();
|
private reorderSingleRowNotifier = new ChangeNotifier<ReorderSingleRowNotifyValue>();
|
||||||
|
|
||||||
private _listener?: DatabaseNotificationObserver;
|
private _listener?: DatabaseNotificationObserver;
|
||||||
|
|
||||||
constructor(public readonly viewId: string) {}
|
constructor(public readonly viewId: string) {}
|
||||||
|
|
||||||
subscribe = (callbacks: {
|
subscribe = async (callbacks: {
|
||||||
onRowsVisibilityChanged?: (value: RowsVisibilityNotifyValue) => void;
|
onRowsVisibilityChanged?: (value: RowsVisibilityNotifyValue) => void;
|
||||||
onNumberOfRowsChanged?: (value: RowsNotifyValue) => void;
|
onNumberOfRowsChanged?: (value: RowsNotifyValue) => void;
|
||||||
onReorderRows?: (value: ReorderRowsNotifyValue) => void;
|
onReorderRows?: (value: ReorderRowsNotifyValue) => void;
|
||||||
onReorderSingleRow?: (value: ReorderSingleRowNotifyValue) => void;
|
onReorderSingleRow?: (value: ReorderSingleRowNotifyValue) => void;
|
||||||
}) => {
|
}) => {
|
||||||
//
|
//
|
||||||
this._rowsVisibilityNotifier.observer.subscribe(callbacks.onRowsVisibilityChanged);
|
this.rowsVisibilityNotifier.observer.subscribe(callbacks.onRowsVisibilityChanged);
|
||||||
this._rowsNotifier.observer.subscribe(callbacks.onNumberOfRowsChanged);
|
this.rowsNotifier.observer.subscribe(callbacks.onNumberOfRowsChanged);
|
||||||
this._reorderRowsNotifier.observer.subscribe(callbacks.onReorderRows);
|
this.reorderRowsNotifier.observer.subscribe(callbacks.onReorderRows);
|
||||||
this._reorderSingleRowNotifier.observer.subscribe(callbacks.onReorderSingleRow);
|
this.reorderSingleRowNotifier.observer.subscribe(callbacks.onReorderSingleRow);
|
||||||
|
|
||||||
this._listener = new DatabaseNotificationObserver({
|
this._listener = new DatabaseNotificationObserver({
|
||||||
viewId: this.viewId,
|
viewId: this.viewId,
|
||||||
@ -43,30 +43,30 @@ export class DatabaseViewRowsObserver {
|
|||||||
switch (notification) {
|
switch (notification) {
|
||||||
case DatabaseNotification.DidUpdateViewRowsVisibility:
|
case DatabaseNotification.DidUpdateViewRowsVisibility:
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._rowsVisibilityNotifier.notify(Ok(RowsVisibilityChangesetPB.deserializeBinary(result.val)));
|
this.rowsVisibilityNotifier.notify(Ok(RowsVisibilityChangesetPB.deserializeBinary(result.val)));
|
||||||
} else {
|
} else {
|
||||||
this._rowsVisibilityNotifier.notify(result);
|
this.rowsVisibilityNotifier.notify(result);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DatabaseNotification.DidUpdateViewRows:
|
case DatabaseNotification.DidUpdateViewRows:
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._rowsNotifier.notify(Ok(RowsChangesetPB.deserializeBinary(result.val)));
|
this.rowsNotifier.notify(Ok(RowsChangesetPB.deserializeBinary(result.val)));
|
||||||
} else {
|
} else {
|
||||||
this._rowsNotifier.notify(result);
|
this.rowsNotifier.notify(result);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DatabaseNotification.DidReorderRows:
|
case DatabaseNotification.DidReorderRows:
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._reorderRowsNotifier.notify(Ok(ReorderAllRowsPB.deserializeBinary(result.val).row_orders));
|
this.reorderRowsNotifier.notify(Ok(ReorderAllRowsPB.deserializeBinary(result.val).row_orders));
|
||||||
} else {
|
} else {
|
||||||
this._reorderRowsNotifier.notify(result);
|
this.reorderRowsNotifier.notify(result);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DatabaseNotification.DidReorderSingleRow:
|
case DatabaseNotification.DidReorderSingleRow:
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._reorderSingleRowNotifier.notify(Ok(ReorderSingleRowPB.deserializeBinary(result.val)));
|
this.reorderSingleRowNotifier.notify(Ok(ReorderSingleRowPB.deserializeBinary(result.val)));
|
||||||
} else {
|
} else {
|
||||||
this._reorderSingleRowNotifier.notify(result);
|
this.reorderSingleRowNotifier.notify(result);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -74,13 +74,14 @@ export class DatabaseViewRowsObserver {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
await this._listener.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
unsubscribe = async () => {
|
unsubscribe = async () => {
|
||||||
this._rowsVisibilityNotifier.unsubscribe();
|
this.rowsVisibilityNotifier.unsubscribe();
|
||||||
this._reorderRowsNotifier.unsubscribe();
|
this.reorderRowsNotifier.unsubscribe();
|
||||||
this._rowsNotifier.unsubscribe();
|
this.rowsNotifier.unsubscribe();
|
||||||
this._reorderSingleRowNotifier.unsubscribe();
|
this.reorderSingleRowNotifier.unsubscribe();
|
||||||
await this._listener?.stop();
|
await this._listener?.stop();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,14 @@ import { FolderNotificationObserver } from '../notifications/observer';
|
|||||||
export type AppUpdateNotifyValue = Result<AppPB, FlowyError>;
|
export type AppUpdateNotifyValue = Result<AppPB, FlowyError>;
|
||||||
export type AppUpdateNotifyCallback = (value: AppUpdateNotifyValue) => void;
|
export type AppUpdateNotifyCallback = (value: AppUpdateNotifyValue) => void;
|
||||||
|
|
||||||
export class WorkspaceObserver {
|
export class AppObserver {
|
||||||
_appNotifier = new ChangeNotifier<AppUpdateNotifyValue>();
|
_appNotifier = new ChangeNotifier<AppUpdateNotifyValue>();
|
||||||
_listener?: FolderNotificationObserver;
|
_listener?: FolderNotificationObserver;
|
||||||
|
|
||||||
constructor(public readonly appId: string) {}
|
constructor(public readonly appId: string) {}
|
||||||
|
|
||||||
subscribe = (callbacks: { onAppChanged: AppUpdateNotifyCallback }) => {
|
subscribe = async (callbacks: { onAppChanged: AppUpdateNotifyCallback }) => {
|
||||||
this._appNotifier?.observer.subscribe(callbacks.onAppChanged);
|
this._appNotifier?.observer.subscribe(callbacks.onAppChanged);
|
||||||
|
|
||||||
this._listener = new FolderNotificationObserver({
|
this._listener = new FolderNotificationObserver({
|
||||||
viewId: this.appId,
|
viewId: this.appId,
|
||||||
parserHandler: (notification, result) => {
|
parserHandler: (notification, result) => {
|
||||||
@ -31,7 +30,7 @@ export class WorkspaceObserver {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return undefined;
|
await this._listener.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
unsubscribe = async () => {
|
unsubscribe = async () => {
|
||||||
|
@ -18,7 +18,7 @@ export class ViewObserver {
|
|||||||
|
|
||||||
constructor(public readonly viewId: string) {}
|
constructor(public readonly viewId: string) {}
|
||||||
|
|
||||||
subscribe = (callbacks: {
|
subscribe = async (callbacks: {
|
||||||
onViewUpdate?: (value: UpdateViewNotifyValue) => void;
|
onViewUpdate?: (value: UpdateViewNotifyValue) => void;
|
||||||
onViewDelete?: (value: DeleteViewNotifyValue) => void;
|
onViewDelete?: (value: DeleteViewNotifyValue) => void;
|
||||||
onViewRestored?: (value: RestoreViewNotifyValue) => void;
|
onViewRestored?: (value: RestoreViewNotifyValue) => void;
|
||||||
@ -77,7 +77,7 @@ export class ViewObserver {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return undefined;
|
await this._listener.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
unsubscribe = async () => {
|
unsubscribe = async () => {
|
||||||
|
@ -9,32 +9,35 @@ export type WorkspaceNotifyValue = Result<WorkspacePB, FlowyError>;
|
|||||||
export type WorkspaceNotifyCallback = (value: WorkspaceNotifyValue) => void;
|
export type WorkspaceNotifyCallback = (value: WorkspaceNotifyValue) => void;
|
||||||
|
|
||||||
export class WorkspaceObserver {
|
export class WorkspaceObserver {
|
||||||
private _appListNotifier = new ChangeNotifier<AppListNotifyValue>();
|
private appListNotifier = new ChangeNotifier<AppListNotifyValue>();
|
||||||
private _workspaceNotifier = new ChangeNotifier<WorkspaceNotifyValue>();
|
private workspaceNotifier = new ChangeNotifier<WorkspaceNotifyValue>();
|
||||||
private _listener?: FolderNotificationObserver;
|
private listener?: FolderNotificationObserver;
|
||||||
|
|
||||||
constructor(public readonly workspaceId: string) {}
|
constructor(public readonly workspaceId: string) {}
|
||||||
|
|
||||||
subscribe = (callbacks: { onAppListChanged: AppListNotifyCallback; onWorkspaceChanged: WorkspaceNotifyCallback }) => {
|
subscribe = async (callbacks: {
|
||||||
this._appListNotifier?.observer.subscribe(callbacks.onAppListChanged);
|
onAppListChanged: AppListNotifyCallback;
|
||||||
this._workspaceNotifier?.observer.subscribe(callbacks.onWorkspaceChanged);
|
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,
|
viewId: this.workspaceId,
|
||||||
parserHandler: (notification, result) => {
|
parserHandler: (notification, result) => {
|
||||||
switch (notification) {
|
switch (notification) {
|
||||||
case FolderNotification.DidUpdateWorkspace:
|
case FolderNotification.DidUpdateWorkspace:
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._workspaceNotifier?.notify(Ok(WorkspacePB.deserializeBinary(result.val)));
|
this.workspaceNotifier?.notify(Ok(WorkspacePB.deserializeBinary(result.val)));
|
||||||
} else {
|
} else {
|
||||||
this._workspaceNotifier?.notify(result);
|
this.workspaceNotifier?.notify(result);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FolderNotification.DidUpdateWorkspaceApps:
|
case FolderNotification.DidUpdateWorkspaceApps:
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
this._appListNotifier?.notify(Ok(RepeatedAppPB.deserializeBinary(result.val).items));
|
this.appListNotifier?.notify(Ok(RepeatedAppPB.deserializeBinary(result.val).items));
|
||||||
} else {
|
} else {
|
||||||
this._appListNotifier?.notify(result);
|
this.appListNotifier?.notify(result);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -42,12 +45,12 @@ export class WorkspaceObserver {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return undefined;
|
await this.listener.start();
|
||||||
};
|
};
|
||||||
|
|
||||||
unsubscribe = async () => {
|
unsubscribe = async () => {
|
||||||
this._appListNotifier.unsubscribe();
|
this.appListNotifier.unsubscribe();
|
||||||
this._workspaceNotifier.unsubscribe();
|
this.workspaceNotifier.unsubscribe();
|
||||||
await this._listener?.stop();
|
await this.listener?.stop();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { listen, UnlistenFn } from '@tauri-apps/api/event';
|
import { listen, UnlistenFn } from "@tauri-apps/api/event";
|
||||||
import { SubscribeObject } from '../models/flowy-notification';
|
import { SubscribeObject } from "../models/flowy-notification";
|
||||||
import { NotificationParser } from './parser';
|
import { NotificationParser } from "./parser";
|
||||||
|
|
||||||
export abstract class AFNotificationObserver<T> {
|
export abstract class AFNotificationObserver<T> {
|
||||||
parser?: NotificationParser<T> | null;
|
parser?: NotificationParser<T> | null;
|
||||||
@ -11,9 +11,15 @@ export abstract class AFNotificationObserver<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start() {
|
async start() {
|
||||||
this._listener = await listen('af-notification', (notification) => {
|
this._listener = await listen("af-notification", (notification) => {
|
||||||
const object = SubscribeObject.fromObject(notification.payload as {});
|
const object: SubscribeObject = SubscribeObject.fromObject(notification.payload as {});
|
||||||
this.parser?.parse(object);
|
if (this.parser?.id !== undefined) {
|
||||||
|
if (object.id === this.parser.id) {
|
||||||
|
this.parser?.parse(object);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.parser?.parse(object);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,14 +24,14 @@ export async function {{ event_func_name }}(): Promise<Result<{{ output_deserial
|
|||||||
if (result.code == 0) {
|
if (result.code == 0) {
|
||||||
{%- if has_output %}
|
{%- if has_output %}
|
||||||
let object = {{ output_deserializer }}.deserializeBinary(result.payload);
|
let object = {{ output_deserializer }}.deserializeBinary(result.payload);
|
||||||
console.log("Success:" + JSON.stringify(object.toObject()))
|
console.log({{ event_func_name }}.name, object);
|
||||||
return Ok(object);
|
return Ok(object);
|
||||||
{%- else %}
|
{%- else %}
|
||||||
return Ok.EMPTY;
|
return Ok.EMPTY;
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
} else {
|
} else {
|
||||||
let error = {{ error_deserializer }}.deserializeBinary(result.payload);
|
let error = {{ error_deserializer }}.deserializeBinary(result.payload);
|
||||||
console.log("Error:" + JSON.stringify(error.toObject()))
|
console.log({{ event_func_name }}.name, error);
|
||||||
return Err(error);
|
return Err(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ impl TryInto<CreateRowParams> for CreateRowPayloadPB {
|
|||||||
type Error = ErrorCode;
|
type Error = ErrorCode;
|
||||||
|
|
||||||
fn try_into(self) -> Result<CreateRowParams, Self::Error> {
|
fn try_into(self) -> Result<CreateRowParams, Self::Error> {
|
||||||
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 {
|
Ok(CreateRowParams {
|
||||||
view_id: view_id.0,
|
view_id: view_id.0,
|
||||||
|
Reference in New Issue
Block a user