mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 14:27:02 +08:00
refactor(core): refactor editor query string selector (#8058)
The editor selector is the information for locating a block, which can automatically focus on a certain content when a user opens a document.
```
export type EditorSelector = {
blockIds?: string[];
elementIds?: string[];
};
```
The selector can be set from multiple places, such as passing it in the center peek parameter, or passing it in the query part of the URL.
This pr decoupled the selector from the query string and now available at `editorService.editor.selector$`
This commit is contained in:
@@ -23,6 +23,8 @@ import {
|
||||
throttleTime,
|
||||
} from 'rxjs';
|
||||
|
||||
import { shallowEqual } from '../utils/shallow-equal';
|
||||
|
||||
const logger = new DebugLogger('livedata');
|
||||
|
||||
/**
|
||||
@@ -334,6 +336,32 @@ export class LiveData<T = unknown>
|
||||
return sub$;
|
||||
}
|
||||
|
||||
/**
|
||||
* same as map, but do shallow equal check before emit
|
||||
*/
|
||||
selector<R>(selector: (v: T) => R): LiveData<R> {
|
||||
const sub$ = LiveData.from(
|
||||
new Observable<R>(subscriber => {
|
||||
let last: any = undefined;
|
||||
return this.subscribe({
|
||||
next: v => {
|
||||
const data = selector(v);
|
||||
if (!shallowEqual(last, data)) {
|
||||
subscriber.next(data);
|
||||
}
|
||||
last = data;
|
||||
},
|
||||
complete: () => {
|
||||
sub$.complete();
|
||||
},
|
||||
});
|
||||
}),
|
||||
undefined as R // is safe
|
||||
);
|
||||
|
||||
return sub$;
|
||||
}
|
||||
|
||||
distinctUntilChanged(comparator?: (previous: T, current: T) => boolean) {
|
||||
return LiveData.from(
|
||||
this.pipe(distinctUntilChanged(comparator)),
|
||||
|
||||
34
packages/common/infra/src/utils/shallow-equal.ts
Normal file
34
packages/common/infra/src/utils/shallow-equal.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
// credit: https://github.com/facebook/fbjs/blob/main/packages/fbjs/src/core/shallowEqual.js
|
||||
export function shallowEqual(objA: any, objB: any) {
|
||||
if (Object.is(objA, objB)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
typeof objA !== 'object' ||
|
||||
objA === null ||
|
||||
typeof objB !== 'object' ||
|
||||
objB === null
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const keysA = Object.keys(objA);
|
||||
const keysB = Object.keys(objB);
|
||||
|
||||
if (keysA.length !== keysB.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test for A's keys different from B.
|
||||
for (const key of keysA) {
|
||||
if (
|
||||
!Object.prototype.hasOwnProperty.call(objB, key) ||
|
||||
!Object.is(objA[key], objB[key])
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user