blob: decbdb07ed5a782276aaf95e65260d9118765a86 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:fidl/fidl.dart';
import 'package:fidl_fuchsia_cobalt/fidl_async.dart' as cobalt;
import 'package:fidl_fuchsia_device_manager/fidl_async.dart' as devmgr;
import 'package:fidl_fuchsia_modular_auth/fidl_async.dart';
import 'package:fidl_fuchsia_sys/fidl_async.dart';
import 'package:fidl_fuchsia_ui_policy/fidl_async.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:lib.base_shell/base_model.dart';
import 'package:lib.widgets/model.dart';
import 'package:zircon/zircon.dart';
import 'package:fuchsia_logger/logger.dart';
export 'package:lib.widgets/model.dart'
show ScopedModel, ScopedModelDescendant, ModelFinder;
/// Function signature for GetPresentationMode callback
typedef GetPresentationModeCallback = void Function(PresentationMode mode);
const Duration _kShowLoadingSpinnerDelay = Duration(milliseconds: 500);
/// Model that provides common state
class UserPickerBaseShellModel extends CommonBaseShellModel
with TickerProviderModelMixin
implements
ServiceProvider,
KeyboardCaptureListenerHack,
PointerCaptureListenerHack {
/// Called when the base shell stops.
final VoidCallback onBaseShellStopped;
/// Called when wifi is tapped.
final VoidCallback onWifiTapped;
/// Called when a user is logging in.
final VoidCallback onLogin;
bool _showingUserActions = false;
bool _addingUser = false;
bool _loadingChildView = false;
final Set<Account> _draggedUsers = <Account>{};
/// Constructor
UserPickerBaseShellModel({
this.onBaseShellStopped,
this.onWifiTapped,
this.onLogin,
cobalt.Logger logger,
}) : super(logger);
@override
void onStop() {
onBaseShellStopped?.call();
super.dispose();
super.onStop();
}
/// Refreshes the list of users.
@override
Future<void> refreshUsers() async {
_updateShowLoadingSpinner();
notifyListeners();
await super.refreshUsers();
_updateShowLoadingSpinner();
notifyListeners();
}
/// Call when wifi is tapped.
void wifiTapped() {
onWifiTapped?.call();
}
/// Call when reset is tapped.
void resetTapped() async {
final ChannelPair channels = ChannelPair();
if (channels.status != 0) {
log.severe('Unable to create channels: $channels.status');
return;
}
int status = System.connectToService(
'/svc/${devmgr.Administrator.$serviceName}',
channels.second.passHandle());
if (status != 0 ) {
channels.first.close();
log.severe('Unable to connect to device administrator service: $status');
return;
}
final devmgr.AdministratorProxy admin = devmgr.AdministratorProxy();
admin.ctrl.bind(InterfaceHandle<devmgr.Administrator>(channels.first));
status = await admin.suspend(devmgr.suspendFlagReboot);
if (status != 0) {
log.severe('Reboot call failed with status: $status');
}
admin.ctrl.close();
}
/// Create a new user and login with that user
@override
Future createAndLoginUser() async {
_addingUser = true;
_updateShowLoadingSpinner();
await super.createAndLoginUser();
_addingUser = false;
_updateShowLoadingSpinner();
notifyListeners();
}
/// Login with given user
@override
Future<void> login(String accountId) async {
_loadingChildView = true;
_updateShowLoadingSpinner();
notifyListeners();
await super.login(accountId);
_loadingChildView = false;
_updateShowLoadingSpinner();
notifyListeners();
}
/// Show advanced user actions such as:
/// * Guest login
/// * Create new account
void showUserActions() {
_showingUserActions = true;
notifyListeners();
}
/// Hide advanced user actions such as:
void hideUserActions() {
_showingUserActions = false;
notifyListeners();
}
/// Add a user to the list of dragged users
void addDraggedUser(Account account) {
_draggedUsers.add(account);
notifyListeners();
}
/// Remove a user from the list of dragged users
void removeDraggedUser(Account account) {
_draggedUsers.remove(account);
notifyListeners();
}
/// Show the loading spinner if true
bool get showingLoadingSpinner => _showingLoadingSpinner;
/// Show the system clock if true
bool get showingClock => !showingLoadingSpinner && _draggedUsers.isEmpty;
/// If true, show advanced user actions
bool get showingUserActions => _showingUserActions;
/// If true, show the remove user target
bool get showingRemoveUserTarget => _draggedUsers.isNotEmpty;
/// Returns true the add user dialog is showing
bool get addingUser => _addingUser;
/// Returns true if we are "loading" the child view
bool get loadingChildView => _loadingChildView;
bool _showingLoadingSpinner = true;
Timer _showLoadingSpinnerTimer;
void _updateShowLoadingSpinner() {
if (accounts == null || _addingUser || _loadingChildView) {
if (_showingLoadingSpinner == null) {
_showLoadingSpinnerTimer = Timer(
_kShowLoadingSpinnerDelay,
() {
_showingLoadingSpinner = true;
_showLoadingSpinnerTimer = null;
notifyListeners();
},
);
}
} else {
_showLoadingSpinnerTimer?.cancel();
_showLoadingSpinnerTimer = null;
_showingLoadingSpinner = false;
notifyListeners();
}
}
}