Skip to content

Commit

Permalink
Update example
Browse files Browse the repository at this point in the history
  • Loading branch information
PlugFox committed Aug 12, 2023
1 parent f6ce9af commit 31bdbe6
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 40 deletions.
10 changes: 7 additions & 3 deletions example/lib/src/feature/authentication/model/user.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ class UnauthenticatedUser extends User {

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is UnauthenticatedUser && username == other.username;
identical(this, other) || other is UnauthenticatedUser;

@override
String toString() => 'UnauthenticatedUser()';
Expand Down Expand Up @@ -127,7 +126,12 @@ final class AuthenticatedUser extends User {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is AuthenticatedUser && username == other.username;
other is AuthenticatedUser &&
username == other.username &&
endpoint == other.endpoint &&
token == other.token &&
channel == other.channel &&
secret == other.secret;

@override
String toString() => 'AuthenticatedUser(username: $username)';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:spinifyapp/src/common/controller/droppable_controller_concurrency.dart';
import 'package:spinifyapp/src/common/controller/state_controller.dart';
import 'package:spinifyapp/src/feature/chat/controller/chat_connection_state.dart';
import 'package:spinifyapp/src/feature/chat/data/chat_repository.dart';

final class ChatConnectionController
extends StateController<ChatConnectionState>
with DroppableControllerConcurrency {
ChatConnectionController({required IChatRepository repository})
: _repository = repository,
super(initialState: repository.connectionState) {
_repository.connectionStates.distinct().listen(setState);
}

final IChatRepository _repository;

void connect(String url) => handle(() => _repository.connect(url));

void disconnect() => handle(_repository.disconnect);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum ChatConnectionState {
disconnected,
connecting,
connected,
}
66 changes: 66 additions & 0 deletions example/lib/src/feature/chat/data/chat_repository.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import 'dart:async';

import 'package:spinify/spinify.dart';
import 'package:spinifyapp/src/feature/chat/controller/chat_connection_state.dart';

/// Chat repository
abstract interface class IChatRepository {
Stream<SpinifyMessage> get messages;

/// Connection state
ChatConnectionState get connectionState;

/// Connection states stream
Stream<ChatConnectionState> get connectionStates;

/// Connect to chat server
Future<void> connect(String url);

/// Disconnect from chat server
Future<void> disconnect();

/// Dispose
Future<void> dispose();
}

final class ChatRepositorySpinifyImpl implements IChatRepository {
ChatRepositorySpinifyImpl({required FutureOr<String?> Function()? getToken})
: _spinify = Spinify(
SpinifyConfig(
getToken: getToken,
),
);

/// Centrifugo client
final Spinify _spinify;

@override
ChatConnectionState get connectionState =>
_spinifyStateToConnectionState(_spinify.state);

@override
late final Stream<ChatConnectionState> connectionStates =
_spinify.states.map<ChatConnectionState>(_spinifyStateToConnectionState);

ChatConnectionState _spinifyStateToConnectionState(SpinifyState state) =>
switch (state) {
SpinifyState$Connected _ => ChatConnectionState.connected,
SpinifyState$Connecting _ => ChatConnectionState.connecting,
SpinifyState$Disconnected _ => ChatConnectionState.disconnected,
SpinifyState$Closed _ => ChatConnectionState.disconnected,
};

@override
Stream<SpinifyMessage> get messages => throw UnimplementedError();

@override
Future<void> connect(String url) => _spinify.connect(url);

@override
Future<void> disconnect() => _spinify.disconnect();

@override
Future<void> dispose() async {
await _spinify.close();
}
}
56 changes: 35 additions & 21 deletions example/lib/src/feature/chat/widget/chat_room.dart
Original file line number Diff line number Diff line change
@@ -1,59 +1,73 @@
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
import 'package:spinifyapp/src/common/controller/state_consumer.dart';
import 'package:spinifyapp/src/feature/authentication/model/user.dart';
import 'package:spinifyapp/src/feature/chat/controller/chat_connection_controller.dart';
import 'package:spinifyapp/src/feature/chat/controller/chat_connection_state.dart';
import 'package:spinifyapp/src/feature/chat/data/chat_repository.dart';

/// {@template chat_screen}
/// ChatRoom widget.
/// {@endtemplate}
class ChatRoom extends StatefulWidget {
/// {@macro chat_screen}
const ChatRoom({super.key});
const ChatRoom({required this.user, super.key});

/// The state from the closest instance of this class
/// that encloses the given context, if any.
@internal
static _ChatRoomState? maybeOf(BuildContext context) =>
context.findAncestorStateOfType<_ChatRoomState>();
/// The user that is currently logged in
final AuthenticatedUser user;

@override
State<ChatRoom> createState() => _ChatRoomState();
}

/// State for widget ChatRoom.
class _ChatRoomState extends State<ChatRoom> {
/* #region Lifecycle */
late final IChatRepository _repository;
late final ChatConnectionController _chatConnectionController;

@override
void initState() {
super.initState();
// Initial state initialization
_repository = ChatRepositorySpinifyImpl(getToken: () => widget.user.token);
_chatConnectionController =
ChatConnectionController(repository: _repository);
_chatConnectionController.connect(widget.user.endpoint);
}

@override
void didUpdateWidget(ChatRoom oldWidget) {
void didUpdateWidget(covariant ChatRoom oldWidget) {
super.didUpdateWidget(oldWidget);
// Widget configuration changed
}

@override
void didChangeDependencies() {
super.didChangeDependencies();
// The configuration of InheritedWidgets has changed
// Also called after initState but before build
if (oldWidget.user != widget.user) {
_chatConnectionController.disconnect();
_chatConnectionController.connect(widget.user.endpoint);
}
}

@override
void dispose() {
// Permanent removal of a tree stent
_chatConnectionController.dispose();
_repository.dispose();
super.dispose();
}
/* #endregion */

@override
Widget build(BuildContext context) => Center(
child: StateConsumer(
controller: _chatConnectionController,
builder: (context, state, child) => switch (state) {
ChatConnectionState.connecting => const CircularProgressIndicator(),
ChatConnectionState.connected => const Text('Connected'),
ChatConnectionState.disconnected => const Text('Disconnected'),
},
),
);

/* @override
Widget build(BuildContext context) => ListView.builder(
scrollDirection: Axis.vertical,
reverse: true,
itemCount: 1000,
itemBuilder: (context, index) => ListTile(
title: Text('Item $index'),
),
);
); */
}
18 changes: 2 additions & 16 deletions example/lib/src/feature/chat/widget/chat_screen.dart
Original file line number Diff line number Diff line change
@@ -1,30 +1,16 @@
import 'package:flutter/material.dart';
import 'package:spinifyapp/src/common/controller/state_consumer.dart';
import 'package:spinifyapp/src/common/localization/localization.dart';
import 'package:spinifyapp/src/feature/authentication/controller/authentication_controller.dart';
import 'package:spinifyapp/src/feature/authentication/widget/authentication_scope.dart';
import 'package:spinifyapp/src/feature/chat/widget/chat_room.dart';

/// {@template chat_screen}
/// ChatScreen widget.
/// {@endtemplate}
class ChatScreen extends StatefulWidget {
class ChatScreen extends StatelessWidget {
/// {@macro chat_screen}
const ChatScreen({super.key});

@override
State<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
late final AuthenticationController authController;

@override
void initState() {
super.initState();
authController = AuthenticationScope.controllerOf(context);
}

@override
Widget build(BuildContext context) {
final authController = AuthenticationScope.controllerOf(context);
Expand All @@ -49,7 +35,7 @@ class _ChatScreenState extends State<ChatScreen> {
body: AnimatedSwitcher(
duration: const Duration(milliseconds: 250),
child: state.user.map<Widget>(
authenticated: (user) => const ChatRoom(),
authenticated: (user) => ChatRoom(user: user),
unauthenticated: (_) => const SizedBox.expand(),
),
),
Expand Down

0 comments on commit 31bdbe6

Please sign in to comment.