mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: collab cursor/selection (#4983)
* feat: support collab selection * feat: collab cusro/selection * chore: add metadata field * feat: support displaying user name above cursor * fix: emit error * feat: support displaying collaborators * feat: sync collaborator * fix: collab doc issues * chore: update deps * feat: refactor device id * chore: enable share button * chore: update collab a816214 * fix: clippy lint * chore: use extension type instead class function * feat: add clear recent views button in debug mode * chore: support clear recent views * feat: support saving the last opened workspace * chore: update collab
This commit is contained in:
@ -1,54 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/document_notification.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart';
|
||||
import 'package:appflowy_backend/rust_stream.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
class DocumentListener {
|
||||
DocumentListener({
|
||||
required this.id,
|
||||
});
|
||||
|
||||
final String id;
|
||||
|
||||
StreamSubscription<SubscribeObject>? _subscription;
|
||||
DocumentNotificationParser? _parser;
|
||||
|
||||
Function(DocEventPB docEvent)? didReceiveUpdate;
|
||||
|
||||
void start({
|
||||
Function(DocEventPB docEvent)? didReceiveUpdate,
|
||||
}) {
|
||||
this.didReceiveUpdate = didReceiveUpdate;
|
||||
|
||||
_parser = DocumentNotificationParser(
|
||||
id: id,
|
||||
callback: _callback,
|
||||
);
|
||||
_subscription = RustStreamReceiver.listen(
|
||||
(observable) => _parser?.parse(observable),
|
||||
);
|
||||
}
|
||||
|
||||
void _callback(
|
||||
DocumentNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DocumentNotification.DidReceiveUpdate:
|
||||
result.map((r) => didReceiveUpdate?.call(DocEventPB.fromBuffer(r)));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _subscription?.cancel();
|
||||
_subscription = null;
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:appflowy/core/notification/document_notification.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart';
|
||||
import 'package:appflowy_backend/rust_stream.dart';
|
||||
import 'package:appflowy_result/appflowy_result.dart';
|
||||
|
||||
class DocumentSyncStateListener {
|
||||
DocumentSyncStateListener({
|
||||
required this.id,
|
||||
});
|
||||
|
||||
final String id;
|
||||
StreamSubscription<SubscribeObject>? _subscription;
|
||||
DocumentNotificationParser? _parser;
|
||||
Function(DocumentSyncStatePB syncState)? didReceiveSyncState;
|
||||
|
||||
void start({
|
||||
Function(DocumentSyncStatePB syncState)? didReceiveSyncState,
|
||||
}) {
|
||||
this.didReceiveSyncState = didReceiveSyncState;
|
||||
|
||||
_parser = DocumentNotificationParser(
|
||||
id: id,
|
||||
callback: _callback,
|
||||
);
|
||||
_subscription = RustStreamReceiver.listen(
|
||||
(observable) => _parser?.parse(observable),
|
||||
);
|
||||
}
|
||||
|
||||
void _callback(
|
||||
DocumentNotification ty,
|
||||
FlowyResult<Uint8List, FlowyError> result,
|
||||
) {
|
||||
switch (ty) {
|
||||
case DocumentNotification.DidUpdateDocumentSyncState:
|
||||
result.map(
|
||||
(r) {
|
||||
final value = DocumentSyncStatePB.fromBuffer(r);
|
||||
didReceiveSyncState?.call(value);
|
||||
},
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> stop() async {
|
||||
await _subscription?.cancel();
|
||||
_subscription = null;
|
||||
}
|
||||
}
|
@ -1,5 +1,8 @@
|
||||
import 'package:appflowy/core/config/kv.dart';
|
||||
import 'package:appflowy/core/config/kv_keys.dart';
|
||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||
import 'package:appflowy/shared/feature_flags.dart';
|
||||
import 'package:appflowy/startup/startup.dart';
|
||||
import 'package:appflowy/user/application/user_service.dart';
|
||||
import 'package:appflowy_backend/log.dart';
|
||||
import 'package:appflowy_backend/protobuf/flowy-error/code.pbenum.dart';
|
||||
@ -135,6 +138,12 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
|
||||
),
|
||||
(e) => state.currentWorkspace,
|
||||
);
|
||||
result.onSuccess((_) async {
|
||||
await getIt<KeyValueStorage>().set(
|
||||
KVKeys.lastOpenedWorkspaceId,
|
||||
workspaceId,
|
||||
);
|
||||
});
|
||||
emit(
|
||||
state.copyWith(
|
||||
currentWorkspace: currentWorkspace,
|
||||
@ -220,11 +229,21 @@ class UserWorkspaceBloc extends Bloc<UserWorkspaceEvent, UserWorkspaceState> {
|
||||
Future<(UserWorkspacePB currentWorkspace, List<UserWorkspacePB> workspaces)?>
|
||||
_fetchWorkspaces() async {
|
||||
try {
|
||||
final lastOpenedWorkspaceId = await getIt<KeyValueStorage>().get(
|
||||
KVKeys.lastOpenedWorkspaceId,
|
||||
);
|
||||
final currentWorkspace =
|
||||
await _userService.getCurrentWorkspace().getOrThrow();
|
||||
final workspaces = await _userService.getWorkspaces().getOrThrow();
|
||||
final currentWorkspaceInList =
|
||||
UserWorkspacePB currentWorkspaceInList =
|
||||
workspaces.firstWhere((e) => e.workspaceId == currentWorkspace.id);
|
||||
if (lastOpenedWorkspaceId != null) {
|
||||
final lastOpenedWorkspace = workspaces
|
||||
.firstWhereOrNull((e) => e.workspaceId == lastOpenedWorkspaceId);
|
||||
if (lastOpenedWorkspace != null) {
|
||||
currentWorkspaceInList = lastOpenedWorkspace;
|
||||
}
|
||||
}
|
||||
return (currentWorkspaceInList, workspaces);
|
||||
} catch (e) {
|
||||
Log.error('fetch workspace error: $e');
|
||||
|
Reference in New Issue
Block a user