684 lines
23 KiB
Dart
684 lines
23 KiB
Dart
part of '../../main.dart';
|
|
|
|
class MainPage extends StatefulWidget {
|
|
MainPage({Key key, this.title}) : super(key: key);
|
|
|
|
final String title;
|
|
|
|
@override
|
|
_MainPageState createState() => new _MainPageState();
|
|
}
|
|
|
|
class _MainPageState extends State<MainPage> with WidgetsBindingObserver, TickerProviderStateMixin {
|
|
|
|
StreamSubscription _stateSubscription;
|
|
StreamSubscription _lovelaceSubscription;
|
|
StreamSubscription _settingsSubscription;
|
|
StreamSubscription _serviceCallSubscription;
|
|
StreamSubscription _showEntityPageSubscription;
|
|
StreamSubscription _showErrorSubscription;
|
|
StreamSubscription _startAuthSubscription;
|
|
StreamSubscription _showPopupSubscription;
|
|
StreamSubscription _reloadUISubscription;
|
|
StreamSubscription _fullReloadSubscription;
|
|
StreamSubscription _showPageSubscription;
|
|
BottomInfoBarController _bottomInfoBarController;
|
|
bool _popupShown = false;
|
|
int _previousViewCount;
|
|
bool _showLoginButton = false;
|
|
bool _preventAppRefresh = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
WidgetsBinding.instance.addObserver(this);
|
|
|
|
_bottomInfoBarController = BottomInfoBarController();
|
|
|
|
_settingsSubscription = eventBus.on<SettingsChangedEvent>().listen((event) {
|
|
Logger.d("Settings change event: reconnect=${event.reconnect}");
|
|
if (event.reconnect) {
|
|
_preventAppRefresh = false;
|
|
_fullLoad();
|
|
}
|
|
});
|
|
|
|
_fullLoad();
|
|
}
|
|
|
|
void _fullLoad() {
|
|
_bottomInfoBarController.showInfoBottomBar(progress: true,);
|
|
Logger.d('[loading] fullLoad');
|
|
_subscribe().then((_) {
|
|
Logger.d('[loading] subscribed');
|
|
ConnectionManager().init(loadSettings: true, forceReconnect: true).then((__){
|
|
Logger.d('[loading] COnnection manager initialized');
|
|
SharedPreferences.getInstance().then((prefs) {
|
|
HomeAssistant().currentDashboardPath = prefs.getString('lovelace_dashboard_url') ?? HomeAssistant.DEFAULT_DASHBOARD;
|
|
_fetchData(useCache: true);
|
|
LocationManager();
|
|
StartupUserMessagesManager().checkMessagesToShow();
|
|
MobileAppIntegrationManager.checkAppRegistration();
|
|
});
|
|
}, onError: (e) {
|
|
if (e is HACNotSetUpException) {
|
|
Navigator.of(context).pushReplacementNamed('/quick-start');
|
|
} else {
|
|
_setErrorState(e);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
void _quickLoad({bool uiOnly: false}) {
|
|
_bottomInfoBarController.showInfoBottomBar(progress: true,);
|
|
ConnectionManager().init(loadSettings: false, forceReconnect: false).then((_){
|
|
_fetchData(useCache: false, uiOnly: uiOnly);
|
|
}, onError: (e) {
|
|
_setErrorState(e);
|
|
});
|
|
}
|
|
|
|
_fetchData({useCache: false, uiOnly: false}) async {
|
|
if (useCache && !uiOnly) {
|
|
HomeAssistant().fetchDataFromCache().then((_) {
|
|
setState((){});
|
|
});
|
|
}
|
|
await HomeAssistant().fetchData(uiOnly).then((_) {
|
|
setState((){
|
|
_bottomInfoBarController.hideBottomBar();
|
|
});
|
|
HomeAssistant().saveCache();
|
|
}).catchError((e) {
|
|
if (e is HACException) {
|
|
_setErrorState(e);
|
|
} else {
|
|
_setErrorState(HACException(e.toString()));
|
|
}
|
|
});
|
|
eventBus.fire(RefreshDataFinishedEvent());
|
|
}
|
|
|
|
@override
|
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
|
Logger.d("$state");
|
|
if (state == AppLifecycleState.resumed && ConnectionManager().settingsLoaded && !_preventAppRefresh) {
|
|
_quickLoad();
|
|
} else if (state == AppLifecycleState.paused && ConnectionManager().settingsLoaded && !_preventAppRefresh) {
|
|
//HomeAssistant().saveCache();
|
|
}
|
|
}
|
|
|
|
Future _subscribe() async {
|
|
if (_stateSubscription == null) {
|
|
_stateSubscription = eventBus.on<StateChangedEvent>().listen((event) {
|
|
if (event.needToRebuildUI) {
|
|
Logger.d("Need to rebuild UI");
|
|
_quickLoad();
|
|
} else {
|
|
setState(() {});
|
|
}
|
|
});
|
|
}
|
|
if (_lovelaceSubscription == null) {
|
|
_lovelaceSubscription = eventBus.on<LovelaceChangedEvent>().listen((event) {
|
|
_quickLoad();
|
|
});
|
|
}
|
|
if (_reloadUISubscription == null) {
|
|
_reloadUISubscription = eventBus.on<ReloadUIEvent>().listen((event){
|
|
_quickLoad(uiOnly: true);
|
|
});
|
|
}
|
|
if (_fullReloadSubscription == null) {
|
|
_fullReloadSubscription = eventBus.on<FullReloadEvent>().listen((event){
|
|
_fullLoad();
|
|
});
|
|
}
|
|
if (_showPopupSubscription == null) {
|
|
_showPopupSubscription = eventBus.on<ShowPopupEvent>().listen((event){
|
|
if (!_popupShown) {
|
|
_popupShown = true;
|
|
if (event.goBackFirst) {
|
|
Navigator.of(context).pop();
|
|
}
|
|
event.popup.show(context).then((_){
|
|
_popupShown = false;
|
|
});
|
|
}
|
|
});
|
|
}
|
|
if (_serviceCallSubscription == null) {
|
|
_serviceCallSubscription =
|
|
eventBus.on<NotifyServiceCallEvent>().listen((event) {
|
|
_notifyServiceCalled(event.domain, event.service, event.entityId);
|
|
});
|
|
}
|
|
|
|
if (_showEntityPageSubscription == null) {
|
|
_showEntityPageSubscription =
|
|
eventBus.on<ShowEntityPageEvent>().listen((event) {
|
|
Logger.d('Showing entity page event handled: ${event.entityId}');
|
|
_showEntityPage(event.entityId);
|
|
});
|
|
}
|
|
|
|
if (_showPageSubscription == null) {
|
|
_showPageSubscription =
|
|
eventBus.on<ShowPageEvent>().listen((event) {
|
|
_showPage(event.path, event.goBackFirst);
|
|
});
|
|
}
|
|
|
|
if (_showErrorSubscription == null) {
|
|
_showErrorSubscription = eventBus.on<ShowErrorEvent>().listen((event){
|
|
_bottomInfoBarController.showErrorBottomBar(event.error);
|
|
});
|
|
}
|
|
|
|
if (_startAuthSubscription == null) {
|
|
_startAuthSubscription = eventBus.on<StartAuthEvent>().listen((event){
|
|
setState(() {
|
|
_showLoginButton = event.showButton;
|
|
});
|
|
if (event.showButton) {
|
|
_showOAuth();
|
|
} else {
|
|
_preventAppRefresh = false;
|
|
Navigator.of(context).pop();
|
|
}
|
|
});
|
|
}
|
|
|
|
/*_firebaseMessaging.getToken().then((String token) {
|
|
HomeAssistant().fcmToken = token;
|
|
completer.complete();
|
|
});*/
|
|
}
|
|
|
|
void _showOAuth() {
|
|
_preventAppRefresh = true;
|
|
Navigator.of(context).pushNamed("/auth", arguments: {"url": AppSettings().oauthUrl});
|
|
}
|
|
|
|
_setErrorState(HACException e) {
|
|
if (e == null) {
|
|
_bottomInfoBarController.showErrorBottomBar(
|
|
HACException("Unknown error")
|
|
);
|
|
} else {
|
|
_bottomInfoBarController.showErrorBottomBar(e);
|
|
}
|
|
}
|
|
|
|
void _notifyServiceCalled(String domain, String service, entityId) {
|
|
_bottomInfoBarController.showInfoBottomBar(
|
|
message: "Calling $domain.$service",
|
|
duration: Duration(seconds: 4)
|
|
);
|
|
}
|
|
|
|
void _showEntityPage(String entityId) {
|
|
Logger.d('Showing entity page: $entityId');
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => EntityViewPage(entityId: entityId),
|
|
)
|
|
);
|
|
/*if (_entityToShow!= null && MediaQuery.of(context).size.width < Sizes.tabletMinWidth) {
|
|
Navigator.push(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => EntityViewPage(entityId: entityId),
|
|
)
|
|
);
|
|
}*/
|
|
}
|
|
|
|
void _showPage(String path, bool goBackFirst) {
|
|
if (goBackFirst) {
|
|
Navigator.pop(context);
|
|
}
|
|
Navigator.pushNamed(
|
|
context,
|
|
path
|
|
);
|
|
}
|
|
|
|
List<Tab> buildUIViewTabs() {
|
|
List<Tab> result = [];
|
|
|
|
if (HomeAssistant().ui.views.isNotEmpty) {
|
|
HomeAssistant().ui.views.forEach((HAView view) {
|
|
result.add(view.buildTab());
|
|
});
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
Drawer _buildAppDrawer() {
|
|
List<Widget> menuItems = [];
|
|
menuItems.add(
|
|
UserAccountsDrawerHeader(
|
|
accountName: Text(HomeAssistant().userName),
|
|
accountEmail: Text(HomeAssistant().locationName ?? ""),
|
|
currentAccountPicture: CircleAvatar(
|
|
backgroundColor: Theme.of(context).backgroundColor,
|
|
child: Text(
|
|
HomeAssistant().userAvatarText,
|
|
style: Theme.of(context).textTheme.display1
|
|
),
|
|
),
|
|
)
|
|
);
|
|
if (HomeAssistant().panels.isNotEmpty) {
|
|
HomeAssistant().panels.forEach((Panel panel) {
|
|
if (!panel.isHidden) {
|
|
menuItems.add(
|
|
panel.getMenuItemWidget(context)
|
|
);
|
|
}
|
|
});
|
|
}
|
|
menuItems.addAll([
|
|
Divider(),
|
|
ListTile(
|
|
leading: Icon(MaterialDesignIcons.getIconDataFromIconName("mdi:cellphone-settings-variant")),
|
|
title: Text("App settings"),
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
Navigator.of(context).pushNamed('/app-settings');
|
|
},
|
|
)
|
|
]);
|
|
menuItems.addAll([
|
|
Divider(),
|
|
new ListTile(
|
|
leading: Icon(MaterialDesignIcons.getIconDataFromIconName("mdi:github-circle")),
|
|
title: Text("Report an issue"),
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
Launcher.launchURLInBrowser("https://github.com/estevez-dev/ha_client/issues/new/choose");
|
|
},
|
|
),
|
|
Divider(),
|
|
new ListTile(
|
|
leading: Icon(MaterialDesignIcons.getIconDataFromIconName("mdi:food")),
|
|
title: Text("Support app development"),
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
Navigator.of(context).pushNamed('/putchase');
|
|
},
|
|
),
|
|
Divider(),
|
|
new ListTile(
|
|
leading: Icon(Icons.help),
|
|
title: Text("Help"),
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
Launcher.launchURLInCustomTab(
|
|
context: context,
|
|
url: "http://ha-client.app/help"
|
|
);
|
|
},
|
|
),
|
|
new ListTile(
|
|
leading: Icon(MaterialDesignIcons.getIconDataFromIconName("mdi:discord")),
|
|
title: Text("Contacts/Discussion"),
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
Launcher.launchURLInBrowser("https://discord.gg/u9vq7QE");
|
|
},
|
|
),
|
|
new ListTile(
|
|
title: Text("What's new?"),
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
Navigator.of(context).pushNamed('/whats-new');
|
|
}
|
|
),
|
|
new AboutListTile(
|
|
aboutBoxChildren: <Widget>[
|
|
GestureDetector(
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
Launcher.launchURLInBrowser("http://ha-client.app/");
|
|
},
|
|
child: Text(
|
|
"ha-client.app",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
color: Colors.blue,
|
|
decoration: TextDecoration.underline,
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
height: 10.0,
|
|
),
|
|
GestureDetector(
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
Launcher.launchURLInCustomTab(context: context, url: "http://ha-client.app/terms_and_conditions");
|
|
},
|
|
child: Text(
|
|
"Terms and Conditions",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
color: Colors.blue,
|
|
decoration: TextDecoration.underline,
|
|
),
|
|
),
|
|
),
|
|
Container(
|
|
height: 10.0,
|
|
),
|
|
GestureDetector(
|
|
onTap: () {
|
|
Navigator.of(context).pop();
|
|
Launcher.launchURLInCustomTab(context: context, url: "http://ha-client.app/privacy_policy");
|
|
},
|
|
child: Text(
|
|
"Privacy Policy",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
color: Colors.blue,
|
|
decoration: TextDecoration.underline,
|
|
),
|
|
),
|
|
)
|
|
],
|
|
applicationName: appName,
|
|
applicationVersion: appVersion
|
|
)
|
|
]);
|
|
return new Drawer(
|
|
child: ListView(
|
|
children: menuItems,
|
|
),
|
|
);
|
|
}
|
|
|
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
|
|
|
Widget _buildScaffoldBody(bool empty) {
|
|
List<Entity> activePlayers = [];
|
|
List<Entity> activeLights = [];
|
|
Color mediaMenuIconColor;
|
|
Color lightMenuIconColor;
|
|
|
|
int currentViewCount = HomeAssistant().ui?.views?.length ?? 0;
|
|
if (_previousViewCount != currentViewCount) {
|
|
Logger.d("Views count changed ($_previousViewCount->$currentViewCount). Creating new tabs controller.");
|
|
_viewsTabController = TabController(vsync: this, length: currentViewCount);
|
|
_previousViewCount = currentViewCount;
|
|
}
|
|
|
|
if (AppSettings().isAuthenticated) {
|
|
_showLoginButton = false;
|
|
}
|
|
|
|
|
|
if (!empty && !HomeAssistant().entities.isEmpty) {
|
|
activePlayers = HomeAssistant().entities.getByDomains(includeDomains: ["media_player"], stateFiler: [EntityState.paused, EntityState.playing, EntityState.idle]);
|
|
activeLights = HomeAssistant().entities.getByDomains(includeDomains: ["light"], stateFiler: [EntityState.on]);
|
|
}
|
|
|
|
if (activePlayers.isNotEmpty) {
|
|
mediaMenuIconColor = Theme.of(context).accentColor;
|
|
} else {
|
|
mediaMenuIconColor = Theme.of(context).primaryIconTheme.color;
|
|
}
|
|
if (activeLights.isNotEmpty) {
|
|
lightMenuIconColor = Theme.of(context).accentColor;
|
|
} else {
|
|
lightMenuIconColor = Theme.of(context).primaryIconTheme.color;
|
|
}
|
|
Widget mainScrollBody;
|
|
if (empty) {
|
|
if (_showLoginButton) {
|
|
mainScrollBody = Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: <Widget>[
|
|
FlatButton(
|
|
child: Text("Login", style: Theme.of(context).textTheme.button),
|
|
color: Theme.of(context).primaryColor,
|
|
onPressed: () => _fullLoad(),
|
|
),
|
|
Container(height: 20,),
|
|
FlatButton(
|
|
child: Text("Login with long-lived token", style: Theme.of(context).textTheme.button),
|
|
color: Theme.of(context).primaryColor,
|
|
onPressed: () => eventBus.fire(ShowPopupEvent(
|
|
popup: TokenLoginPopup()
|
|
))
|
|
),
|
|
Container(height: 20,),
|
|
FlatButton(
|
|
child: Text("Connection settings", style: Theme.of(context).textTheme.button),
|
|
color: Theme.of(context).primaryColor,
|
|
onPressed: () => Navigator.of(context).pushNamed('/connection-settings')
|
|
)
|
|
]
|
|
)
|
|
);
|
|
} else {
|
|
mainScrollBody = Center(
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
children: <Widget>[
|
|
Text("...")
|
|
]
|
|
),
|
|
);
|
|
}
|
|
} else {
|
|
mainScrollBody = HomeAssistant().ui.build(context, _viewsTabController);
|
|
}
|
|
|
|
return NestedScrollView(
|
|
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
|
return <Widget>[
|
|
SliverAppBar(
|
|
floating: true,
|
|
pinned: true,
|
|
snap: false,
|
|
primary: AppSettings().displayMode == DisplayMode.normal,
|
|
title: Text(HomeAssistant().locationName ?? ""),
|
|
actions: <Widget>[
|
|
PopupMenuButton(
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 15),
|
|
child: Icon(MaterialDesignIcons.getIconDataFromIconName(
|
|
"mdi:dots-vertical"), color: Theme.of(context).primaryIconTheme.color)
|
|
),
|
|
onSelected: (String val) {
|
|
if (val == "reload") {
|
|
_quickLoad();
|
|
} else if (val == "logout") {
|
|
HomeAssistant().logout().then((_) {
|
|
_quickLoad();
|
|
});
|
|
}
|
|
},
|
|
itemBuilder: (BuildContext context) {
|
|
List<PopupMenuEntry<String>> result = [
|
|
PopupMenuItem<String>(
|
|
child: new Text("Reload"),
|
|
value: "reload",
|
|
)
|
|
];
|
|
if (AppSettings().isAuthenticated) {
|
|
result.addAll([
|
|
PopupMenuDivider(),
|
|
PopupMenuItem<String>(
|
|
child: new Text("Logout"),
|
|
value: "logout",
|
|
)]);
|
|
}
|
|
return result;
|
|
},
|
|
),
|
|
],
|
|
leading: IconButton(
|
|
icon: Icon(Icons.menu),
|
|
onPressed: () {
|
|
_scaffoldKey.currentState.openDrawer();
|
|
},
|
|
),
|
|
expandedHeight: 130,
|
|
flexibleSpace: FlexibleSpaceBar(
|
|
title: Padding(
|
|
padding: EdgeInsets.only(bottom: 15),
|
|
child: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: <Widget>[
|
|
PopupMenuButton<String>(
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
|
child: Icon(
|
|
MaterialDesignIcons.getIconDataFromIconName("mdi:television"),
|
|
color: mediaMenuIconColor,
|
|
size: 20,
|
|
)
|
|
),
|
|
onSelected: (String val) {
|
|
if (val == "play_media") {
|
|
Navigator.pushNamed(context, "/play-media", arguments: {"url": ""});
|
|
} else if (val != null) {
|
|
_showEntityPage(val);
|
|
}
|
|
},
|
|
itemBuilder: (BuildContext context) {
|
|
List<PopupMenuEntry<String>> result = [
|
|
PopupMenuDivider(),
|
|
PopupMenuItem<String>(
|
|
child: new Text("Play media..."),
|
|
value: "play_media",
|
|
)
|
|
];
|
|
if (activePlayers.isNotEmpty) {
|
|
result.insertAll(0,
|
|
activePlayers.map((entity) => PopupMenuItem<String>(
|
|
child: Text(
|
|
"${entity.displayName}",
|
|
style: Theme.of(context).textTheme.body1.copyWith(
|
|
color: HAClientTheme().getColorByEntityState(entity.state, context)
|
|
)
|
|
),
|
|
value: "${entity.entityId}",
|
|
)).toList()
|
|
);
|
|
} else {
|
|
result.insert(0, PopupMenuItem<String>(
|
|
child: new Text("No active players"),
|
|
value: "_",
|
|
enabled: false,
|
|
));
|
|
}
|
|
return result;
|
|
}
|
|
),
|
|
PopupMenuButton<String>(
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
|
|
child: Icon(
|
|
MaterialDesignIcons.getIconDataFromIconName("mdi:lightbulb-outline"),
|
|
color: lightMenuIconColor,
|
|
size: 20
|
|
)
|
|
),
|
|
onSelected: (String val) {
|
|
if (val == 'turn_off_all') {
|
|
ConnectionManager().callService(
|
|
service: 'turn_off',
|
|
domain: 'light',
|
|
entityId: 'all'
|
|
);
|
|
} else if (val == 'turn_on_all') {
|
|
ConnectionManager().callService(
|
|
service: 'turn_on',
|
|
domain: 'light',
|
|
entityId: 'all'
|
|
);
|
|
}
|
|
},
|
|
itemBuilder: (BuildContext context) => <PopupMenuEntry<String>>[
|
|
PopupMenuItem<String>(
|
|
child: new Text("Turn on all lights"),
|
|
value: "turn_on_all",
|
|
),
|
|
PopupMenuItem<String>(
|
|
child: new Text("Turn off all ligts"),
|
|
value: "turn_off_all",
|
|
enabled: activeLights.isNotEmpty,
|
|
)
|
|
],
|
|
)
|
|
],
|
|
) ),
|
|
centerTitle: true,
|
|
),
|
|
bottom: empty ? null : TabBar(
|
|
controller: _viewsTabController,
|
|
tabs: buildUIViewTabs(),
|
|
isScrollable: true,
|
|
),
|
|
),
|
|
|
|
];
|
|
},
|
|
body: mainScrollBody,
|
|
);
|
|
}
|
|
|
|
TabController _viewsTabController;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (HomeAssistant().isNoViews) {
|
|
return Scaffold(
|
|
key: _scaffoldKey,
|
|
primary: false,
|
|
drawer: _buildAppDrawer(),
|
|
bottomNavigationBar: BottomInfoBar(
|
|
controller: _bottomInfoBarController,
|
|
),
|
|
body: _buildScaffoldBody(true)
|
|
);
|
|
} else {
|
|
return Scaffold(
|
|
key: _scaffoldKey,
|
|
drawer: _buildAppDrawer(),
|
|
primary: false,
|
|
bottomNavigationBar: BottomInfoBar(
|
|
controller: _bottomInfoBarController,
|
|
),
|
|
body: _buildScaffoldBody(false)
|
|
);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
WidgetsBinding.instance.removeObserver(this);
|
|
Hive.close();
|
|
//final flutterWebviewPlugin = new FlutterWebviewPlugin();
|
|
//flutterWebviewPlugin.dispose();
|
|
_viewsTabController?.dispose();
|
|
_stateSubscription?.cancel();
|
|
_lovelaceSubscription?.cancel();
|
|
_settingsSubscription?.cancel();
|
|
_serviceCallSubscription?.cancel();
|
|
_showPopupSubscription?.cancel();
|
|
_showEntityPageSubscription?.cancel();
|
|
_showErrorSubscription?.cancel();
|
|
_startAuthSubscription?.cancel();
|
|
_showPageSubscription?.cancel();
|
|
_fullReloadSubscription?.cancel();
|
|
_reloadUISubscription?.cancel();
|
|
super.dispose();
|
|
}
|
|
}
|