From 2f243b641eaaf8351e3f0cb4b6309f39040ebd90 Mon Sep 17 00:00:00 2001 From: CodeDoctorDE Date: Fri, 17 Jan 2025 20:02:44 +0100 Subject: [PATCH] Rework collaboration system --- app/lib/bloc/document_state.dart | 4 + app/lib/services/network.dart | 70 ++++++----- app/lib/services/network.freezed.dart | 173 -------------------------- app/lib/services/network.g.dart | 11 -- app/lib/views/main.dart | 6 +- app/pubspec.lock | 8 +- app/pubspec.yaml | 4 +- metadata/en-US/changelogs/129.txt | 5 + 8 files changed, 54 insertions(+), 227 deletions(-) diff --git a/app/lib/bloc/document_state.dart b/app/lib/bloc/document_state.dart index a8b46b69f8ab..21b3daa630dd 100644 --- a/app/lib/bloc/document_state.dart +++ b/app/lib/bloc/document_state.dart @@ -129,6 +129,10 @@ abstract class DocumentLoaded extends DocumentState { {Size? viewportSize, double? pixelRatio, bool reset = false}) => currentIndexCubit.bake(this, viewportSize: viewportSize, pixelRatio: pixelRatio, reset: reset); + + @override + Future saveBytes([NoteData? current]) => + saveData().then((e) => e.exportAsBytes()); } class DocumentLoadSuccess extends DocumentLoaded { diff --git a/app/lib/services/network.dart b/app/lib/services/network.dart index ff6929959aff..df8acdf7fc4b 100644 --- a/app/lib/services/network.dart +++ b/app/lib/services/network.dart @@ -15,11 +15,6 @@ import 'package:rxdart/rxdart.dart'; part 'network.freezed.dart'; part 'network.g.dart'; -enum NetworkingSide { - server, - client, -} - enum NetworkingType { webSocket; @@ -29,17 +24,9 @@ enum NetworkingType { } const kDefaultPort = 28005; -const kTimeout = Duration(seconds: 10); +const kTimeout = Duration(minutes: 5); typedef NetworkingState = (NetworkerBase, NamedRpcNetworkerPipe); -@freezed -class NetworkingInitMessage with _$NetworkingInitMessage { - const factory NetworkingInitMessage(List? data) = _NetworkingInitMessage; - - factory NetworkingInitMessage.fromJson(Map json) => - _$NetworkingInitMessageFromJson(json); -} - @freezed class NetworkingUser with _$NetworkingUser { const factory NetworkingUser({ @@ -101,23 +88,32 @@ class NetworkingService { final rpc = NamedRpcServerNetworkerPipe(); _setupRpc(rpc, server); void sendConnections() { - rpc.callFunction(NetworkEvent.connections.index, - Uint8List.fromList(jsonEncode(connections.toList()).codeUnits)); + final current = server.clientConnections; + _connections.add(current); + rpc.sendMessage(RpcNetworkerPacket( + function: NetworkEvent.connections.index, + data: Uint8List.fromList(jsonEncode(current.toList()).codeUnits), + channel: kAuthorityChannel, + )); } server.clientConnect.listen((event) async { final state = _bloc?.state; - rpc.callFunction( - NetworkEvent.init.index, - Uint8List.fromList( - jsonEncode(NetworkingInitMessage((await state?.saveBytes()))) - .codeUnits)); + if (state is! DocumentLoaded) return; + rpc.sendMessage( + RpcNetworkerPacket( + function: NetworkEvent.init.index, + data: await state.saveBytes(), + channel: kAuthorityChannel, + ), + event.$1); sendConnections(); }); server.clientDisconnect.listen((event) { sendConnections(); }); server.connect(rpc); + await server.init(); _subject.add((server, rpc)); } @@ -126,20 +122,18 @@ class NetworkingService { if (!uri.hasPort) { uri = uri.replace(port: kDefaultPort); } + if(!uri.hasScheme) { + uri = uri.replace(scheme: 'ws'); + } final client = NetworkerSocketClient(uri); final rpc = NamedRpcClientNetworkerPipe(); _setupRpc(rpc, client); final completer = Completer(); - rpc - .registerFunction(NetworkEvent.init.index, - mode: RpcNetworkerMode.authority) - .connect(RawJsonNetworkerPlugin() - ..read.listen((message) { - final init = NetworkingInitMessage.fromJson(message.data); - completer.complete( - init.data == null ? null : Uint8List.fromList(init.data!)); - })); + rpc.registerNamedFunction(NetworkEvent.init).read.listen((message) { + completer.complete(message.data); + }); client.connect(rpc); + await client.init(); _subject.add((client, rpc)); return completer.future.timeout(kTimeout); } @@ -179,16 +173,24 @@ class NetworkingService { } void sendUser(NetworkingUser user) { - state?.$2.callNamedFunction(NetworkEvent.user, - Uint8List.fromList(jsonEncode(user.toJson()).codeUnits)); + state?.$2.sendMessage(RpcNetworkerPacket( + function: NetworkEvent.user.index, + data: Uint8List.fromList(jsonEncode(user.toJson()).codeUnits), + channel: kAuthorityChannel, + )); } bool _externalEvent = false; void onEvent(DocumentEvent event) { if (!event.shouldSync() || _externalEvent) return; - state?.$2.callNamedFunction(NetworkEvent.event, - Uint8List.fromList(jsonEncode(event.toJson()).codeUnits)); + state?.$2.sendMessage(RpcNetworkerPacket( + function: NetworkEvent.event.index, + data: Uint8List.fromList( + jsonEncode(event.toJson()).codeUnits, + ), + channel: state?.$1 is NetworkerServer ? kAuthorityChannel : kAnyChannel, + )); } void onMessage(DocumentEvent event) { diff --git a/app/lib/services/network.freezed.dart b/app/lib/services/network.freezed.dart index 864d82b4cef3..7379f8f9100c 100644 --- a/app/lib/services/network.freezed.dart +++ b/app/lib/services/network.freezed.dart @@ -14,179 +14,6 @@ T _$identity(T value) => value; final _privateConstructorUsedError = UnsupportedError( 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); -NetworkingInitMessage _$NetworkingInitMessageFromJson( - Map json) { - return _NetworkingInitMessage.fromJson(json); -} - -/// @nodoc -mixin _$NetworkingInitMessage { - List? get data => throw _privateConstructorUsedError; - - /// Serializes this NetworkingInitMessage to a JSON map. - Map toJson() => throw _privateConstructorUsedError; - - /// Create a copy of NetworkingInitMessage - /// with the given fields replaced by the non-null parameter values. - @JsonKey(includeFromJson: false, includeToJson: false) - $NetworkingInitMessageCopyWith get copyWith => - throw _privateConstructorUsedError; -} - -/// @nodoc -abstract class $NetworkingInitMessageCopyWith<$Res> { - factory $NetworkingInitMessageCopyWith(NetworkingInitMessage value, - $Res Function(NetworkingInitMessage) then) = - _$NetworkingInitMessageCopyWithImpl<$Res, NetworkingInitMessage>; - @useResult - $Res call({List? data}); -} - -/// @nodoc -class _$NetworkingInitMessageCopyWithImpl<$Res, - $Val extends NetworkingInitMessage> - implements $NetworkingInitMessageCopyWith<$Res> { - _$NetworkingInitMessageCopyWithImpl(this._value, this._then); - - // ignore: unused_field - final $Val _value; - // ignore: unused_field - final $Res Function($Val) _then; - - /// Create a copy of NetworkingInitMessage - /// with the given fields replaced by the non-null parameter values. - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? data = freezed, - }) { - return _then(_value.copyWith( - data: freezed == data - ? _value.data - : data // ignore: cast_nullable_to_non_nullable - as List?, - ) as $Val); - } -} - -/// @nodoc -abstract class _$$NetworkingInitMessageImplCopyWith<$Res> - implements $NetworkingInitMessageCopyWith<$Res> { - factory _$$NetworkingInitMessageImplCopyWith( - _$NetworkingInitMessageImpl value, - $Res Function(_$NetworkingInitMessageImpl) then) = - __$$NetworkingInitMessageImplCopyWithImpl<$Res>; - @override - @useResult - $Res call({List? data}); -} - -/// @nodoc -class __$$NetworkingInitMessageImplCopyWithImpl<$Res> - extends _$NetworkingInitMessageCopyWithImpl<$Res, - _$NetworkingInitMessageImpl> - implements _$$NetworkingInitMessageImplCopyWith<$Res> { - __$$NetworkingInitMessageImplCopyWithImpl(_$NetworkingInitMessageImpl _value, - $Res Function(_$NetworkingInitMessageImpl) _then) - : super(_value, _then); - - /// Create a copy of NetworkingInitMessage - /// with the given fields replaced by the non-null parameter values. - @pragma('vm:prefer-inline') - @override - $Res call({ - Object? data = freezed, - }) { - return _then(_$NetworkingInitMessageImpl( - freezed == data - ? _value._data - : data // ignore: cast_nullable_to_non_nullable - as List?, - )); - } -} - -/// @nodoc -@JsonSerializable() -class _$NetworkingInitMessageImpl - with DiagnosticableTreeMixin - implements _NetworkingInitMessage { - const _$NetworkingInitMessageImpl(final List? data) : _data = data; - - factory _$NetworkingInitMessageImpl.fromJson(Map json) => - _$$NetworkingInitMessageImplFromJson(json); - - final List? _data; - @override - List? get data { - final value = _data; - if (value == null) return null; - if (_data is EqualUnmodifiableListView) return _data; - // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(value); - } - - @override - String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'NetworkingInitMessage(data: $data)'; - } - - @override - void debugFillProperties(DiagnosticPropertiesBuilder properties) { - super.debugFillProperties(properties); - properties - ..add(DiagnosticsProperty('type', 'NetworkingInitMessage')) - ..add(DiagnosticsProperty('data', data)); - } - - @override - bool operator ==(Object other) { - return identical(this, other) || - (other.runtimeType == runtimeType && - other is _$NetworkingInitMessageImpl && - const DeepCollectionEquality().equals(other._data, _data)); - } - - @JsonKey(includeFromJson: false, includeToJson: false) - @override - int get hashCode => - Object.hash(runtimeType, const DeepCollectionEquality().hash(_data)); - - /// Create a copy of NetworkingInitMessage - /// with the given fields replaced by the non-null parameter values. - @JsonKey(includeFromJson: false, includeToJson: false) - @override - @pragma('vm:prefer-inline') - _$$NetworkingInitMessageImplCopyWith<_$NetworkingInitMessageImpl> - get copyWith => __$$NetworkingInitMessageImplCopyWithImpl< - _$NetworkingInitMessageImpl>(this, _$identity); - - @override - Map toJson() { - return _$$NetworkingInitMessageImplToJson( - this, - ); - } -} - -abstract class _NetworkingInitMessage implements NetworkingInitMessage { - const factory _NetworkingInitMessage(final List? data) = - _$NetworkingInitMessageImpl; - - factory _NetworkingInitMessage.fromJson(Map json) = - _$NetworkingInitMessageImpl.fromJson; - - @override - List? get data; - - /// Create a copy of NetworkingInitMessage - /// with the given fields replaced by the non-null parameter values. - @override - @JsonKey(includeFromJson: false, includeToJson: false) - _$$NetworkingInitMessageImplCopyWith<_$NetworkingInitMessageImpl> - get copyWith => throw _privateConstructorUsedError; -} - NetworkingUser _$NetworkingUserFromJson(Map json) { return _NetworkingUser.fromJson(json); } diff --git a/app/lib/services/network.g.dart b/app/lib/services/network.g.dart index 416f0f9babcc..0e20db990f3b 100644 --- a/app/lib/services/network.g.dart +++ b/app/lib/services/network.g.dart @@ -6,17 +6,6 @@ part of 'network.dart'; // JsonSerializableGenerator // ************************************************************************** -_$NetworkingInitMessageImpl _$$NetworkingInitMessageImplFromJson(Map json) => - _$NetworkingInitMessageImpl( - (json['data'] as List?)?.map((e) => (e as num).toInt()).toList(), - ); - -Map _$$NetworkingInitMessageImplToJson( - _$NetworkingInitMessageImpl instance) => - { - 'data': instance.data, - }; - _$NetworkingUserImpl _$$NetworkingUserImplFromJson(Map json) => _$NetworkingUserImpl( cursor: _$JsonConverterFromJson, Point>( diff --git a/app/lib/views/main.dart b/app/lib/views/main.dart index 23a54188c2b6..14e9421dbbd5 100644 --- a/app/lib/views/main.dart +++ b/app/lib/views/main.dart @@ -182,13 +182,13 @@ class _ProjectPageState extends State { NoteData? document; var data = widget.data; final uri = Uri.tryParse(widget.uri ?? ''); + var type = widget.type.isEmpty ? (fileType ?? widget.type) : widget.type; if (widget.uri != null && uri != null) { data = await networkingService.createSocketClient(uri); + type = ''; } if (data != null) { - document ??= await globalImportService.load( - type: widget.type.isEmpty ? (fileType ?? widget.type) : widget.type, - data: data); + document ??= await globalImportService.load(type: type, data: data); if (document == null) { GoRouter.of(context).pop(); return; diff --git a/app/pubspec.lock b/app/pubspec.lock index ff82704e3389..583c2f9fd500 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -873,8 +873,8 @@ packages: dependency: "direct main" description: path: "packages/networker/networker" - ref: "071e02761bf55a47bcde0cdc2a711b8ff5fbbb18" - resolved-ref: "071e02761bf55a47bcde0cdc2a711b8ff5fbbb18" + ref: "4d8b20841bcfa644695963c69f3e3032b764d283" + resolved-ref: "4d8b20841bcfa644695963c69f3e3032b764d283" url: "https://github.com/LinwoodDev/dart_pkgs" source: git version: "1.0.0" @@ -882,8 +882,8 @@ packages: dependency: "direct main" description: path: "packages/networker/networker_socket" - ref: "9085d42cf75c3d3edc8edb9ef22697dbbe2bf38c" - resolved-ref: "9085d42cf75c3d3edc8edb9ef22697dbbe2bf38c" + ref: "630928b8588064a0895e45ca91993ce05723811f" + resolved-ref: "630928b8588064a0895e45ca91993ce05723811f" url: "https://github.com/LinwoodDev/dart_pkgs" source: git version: "1.0.0" diff --git a/app/pubspec.yaml b/app/pubspec.yaml index c13af5f5e0bc..2d751443900f 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -89,12 +89,12 @@ dependencies: networker: git: url: https://github.com/LinwoodDev/dart_pkgs - ref: 071e02761bf55a47bcde0cdc2a711b8ff5fbbb18 + ref: 4d8b20841bcfa644695963c69f3e3032b764d283 path: packages/networker/networker networker_socket: git: url: https://github.com/LinwoodDev/dart_pkgs - ref: 9085d42cf75c3d3edc8edb9ef22697dbbe2bf38c + ref: 630928b8588064a0895e45ca91993ce05723811f path: packages/networker/networker_socket lw_file_system: git: diff --git a/metadata/en-US/changelogs/129.txt b/metadata/en-US/changelogs/129.txt index cc50139d1533..ecbcc0ca4c40 100644 --- a/metadata/en-US/changelogs/129.txt +++ b/metadata/en-US/changelogs/129.txt @@ -11,5 +11,10 @@ * Fix lock collection wrongly labeled as Layer * Update secure storage dependency * Use minSdkVersion 23 instead of 21 (The minimum version of android is 6.0 (Marshmallow)) +* Improve collaboration system + * Use wss default if no protocol is provided + * Fix networking server/client not starting + * Fix initializaton not sent by server + * Improve performance when joining a room Read more here: https://linwood.dev/butterfly/2.3.0-beta.1 \ No newline at end of file