diff --git a/packages/neon/neon/lib/neon.dart b/packages/neon/neon/lib/neon.dart index 2bc8e73f..0de68ae2 100644 --- a/packages/neon/neon/lib/neon.dart +++ b/packages/neon/neon/lib/neon.dart @@ -58,7 +58,7 @@ part 'src/blocs/next_push.dart'; part 'src/blocs/push_notifications.dart'; part 'src/blocs/timer.dart'; part 'src/blocs/user_details.dart'; -part 'src/blocs/user_status.dart'; +part 'src/blocs/user_statuses.dart'; part 'src/interfaces/notifications.dart'; part 'src/pages/account_settings.dart'; part 'src/pages/home.dart'; diff --git a/packages/neon/neon/lib/src/blocs/accounts.dart b/packages/neon/neon/lib/src/blocs/accounts.dart index c1d8a16e..1fda9d6b 100644 --- a/packages/neon/neon/lib/src/blocs/accounts.dart +++ b/packages/neon/neon/lib/src/blocs/accounts.dart @@ -74,7 +74,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState final _appsBlocs = {}; final _capabilitiesBlocs = {}; final _userDetailsBlocs = {}; - final _userStatusBlocs = {}; + final _userStatusesBlocs = {}; @override void dispose() { @@ -83,7 +83,7 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState _appsBlocs.disposeAll(); _capabilitiesBlocs.disposeAll(); _userDetailsBlocs.disposeAll(); - _userStatusBlocs.disposeAll(); + _userStatusesBlocs.disposeAll(); for (final options in _accountsOptions.values) { options.dispose(); } @@ -190,12 +190,12 @@ class AccountsBloc extends Bloc implements AccountsBlocEvents, AccountsBlocState ); } - UserStatusBloc getUserStatusBloc(final Account account) { - if (_userStatusBlocs[account.id] != null) { - return _userStatusBlocs[account.id]!; + UserStatusesBloc getUserStatusesBloc(final Account account) { + if (_userStatusesBlocs[account.id] != null) { + return _userStatusesBlocs[account.id]!; } - return _userStatusBlocs[account.id] = UserStatusBloc( + return _userStatusesBlocs[account.id] = UserStatusesBloc( _platform, account, ); diff --git a/packages/neon/neon/lib/src/blocs/user_status.dart b/packages/neon/neon/lib/src/blocs/user_status.dart deleted file mode 100644 index 7704657e..00000000 --- a/packages/neon/neon/lib/src/blocs/user_status.dart +++ /dev/null @@ -1,61 +0,0 @@ -part of '../../neon.dart'; - -abstract class UserStatusBlocEvents {} - -abstract class UserStatusBlocStates { - BehaviorSubject> get userStatus; -} - -class UserStatusBloc extends InteractiveBloc implements UserStatusBlocEvents, UserStatusBlocStates { - UserStatusBloc( - this._platform, - this._account, - ) { - _timer = instantPeriodicTimer( - const Duration(minutes: 5), - (final _) async { - await refresh(); - }, - ); - } - - final NeonPlatform _platform; - final Account _account; - late Timer _timer; - - @override - void dispose() { - _timer.cancel(); - unawaited(userStatus.close()); - } - - @override - BehaviorSubject> userStatus = - BehaviorSubject>(); - - @override - Future refresh() async { - final isAway = - _platform.canUseWindowManager && (!(await windowManager.isFocused()) || !(await windowManager.isVisible())); - try { - final response = await _account.client.userStatus.heartbeat( - status: isAway ? NextcloudUserStatusType.away : NextcloudUserStatusType.online, - ); - userStatus.add(Result.success(response.ocs.data)); - } catch (e) { - if (e is NextcloudApiException && e.statusCode == 204) { - return; - } - userStatus.add(Result.error(e)); - } - } -} - -Timer instantPeriodicTimer( - final Duration duration, - final void Function(Timer timer) callback, -) { - final timer = Timer.periodic(duration, callback); - callback(timer); - return timer; -} diff --git a/packages/neon/neon/lib/src/blocs/user_statuses.dart b/packages/neon/neon/lib/src/blocs/user_statuses.dart new file mode 100644 index 00000000..21b8803f --- /dev/null +++ b/packages/neon/neon/lib/src/blocs/user_statuses.dart @@ -0,0 +1,85 @@ +part of '../../neon.dart'; + +abstract class UserStatusesBlocEvents { + void load(final String username, {final bool force = false}); +} + +abstract class UserStatusesBlocStates { + BehaviorSubject>> get statuses; +} + +class UserStatusesBloc extends InteractiveBloc implements UserStatusesBlocEvents, UserStatusesBlocStates { + UserStatusesBloc( + this._platform, + this._account, + ) { + unawaited(refresh()); + _timer = TimerBloc().registerTimer(const Duration(minutes: 5), refresh); + } + + final NeonPlatform _platform; + final Account _account; + late final NeonTimer _timer; + + @override + void dispose() { + _timer.cancel(); + unawaited(statuses.close()); + super.dispose(); + } + + @override + BehaviorSubject>> statuses = + BehaviorSubject>>(); + + @override + Future refresh() async { + for (final username in _statuses.keys) { + await load(username, force: true); + } + } + + @override + Future load(final String username, {final bool force = false}) async { + if (!force && _statuses.containsKey(username)) { + return; + } + + try { + _updateStatus(username, Result.loading()); + + NextcloudUserStatusPublicStatus? data; + if (_account.username == username) { + final isAway = + _platform.canUseWindowManager && (!(await windowManager.isFocused()) || !(await windowManager.isVisible())); + final response = await _account.client.userStatus.heartbeat( + status: isAway ? NextcloudUserStatusType.away : NextcloudUserStatusType.online, + ); + data = response.ocs.data.userStatusStatus?.userStatusPublicStatus; + } else { + final response = await _account.client.userStatus.getPublicStatus(userId: username); + data = response.ocs.data.userStatusPublicStatus; + } + + _updateStatus(username, Result.success(data)); + } catch (e, s) { + if (e is NextcloudApiException && (e.statusCode == 404 || e.statusCode == 204)) { + _updateStatus(username, Result.success(null)); + return; + } + debugPrint(e.toString()); + debugPrint(s.toString()); + _updateStatus(username, Result.error(e)); + } + } + + Map> get _statuses => + statuses.valueOrNull ?? >{}; + + void _updateStatus(final String username, final Result result) { + statuses.add({ + ..._statuses, + username: result, + }); + } +}