ente/lib/ui/account/sessions_page.dart

228 lines
6.5 KiB
Dart
Raw Normal View History

import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
2021-11-23 20:05:42 +00:00
import 'package:photos/core/configuration.dart';
import 'package:photos/ente_theme_data.dart';
2023-04-04 16:56:36 +00:00
import "package:photos/generated/l10n.dart";
import 'package:photos/models/sessions.dart';
import 'package:photos/services/user_service.dart';
import 'package:photos/ui/common/loading_widget.dart';
import 'package:photos/utils/date_time_util.dart';
2021-11-23 19:54:47 +00:00
import 'package:photos/utils/dialog_util.dart';
import 'package:photos/utils/toast_util.dart';
class SessionsPage extends StatefulWidget {
2022-12-28 04:52:25 +00:00
const SessionsPage({Key? key}) : super(key: key);
@override
2022-07-03 09:45:00 +00:00
State<SessionsPage> createState() => _SessionsPageState();
}
class _SessionsPageState extends State<SessionsPage> {
2022-12-28 04:52:25 +00:00
Sessions? _sessions;
final Logger _logger = Logger("SessionsPageState");
@override
void initState() {
2023-02-03 10:54:38 +00:00
_fetchActiveSessions().onError((error, stackTrace) {
showToast(context, "Failed to fetch active sessions");
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
2023-04-04 16:56:36 +00:00
title: Text(S.of(context).activeSessions),
),
body: _getBody(),
);
}
Widget _getBody() {
if (_sessions == null) {
2022-07-04 06:02:17 +00:00
return const Center(child: EnteLoadingWidget());
}
2022-08-29 14:43:31 +00:00
final List<Widget> rows = [];
2022-07-04 06:02:17 +00:00
rows.add(const Padding(padding: EdgeInsets.all(4)));
2022-12-28 04:52:25 +00:00
for (final session in _sessions!.sessions) {
rows.add(_getSessionWidget(session));
}
2021-11-24 05:40:07 +00:00
return SingleChildScrollView(
child: Column(
children: rows,
),
);
}
Widget _getSessionWidget(Session session) {
final lastUsedTime =
DateTime.fromMicrosecondsSinceEpoch(session.lastUsedTime);
2021-11-23 20:10:51 +00:00
return Column(
children: [
InkWell(
onTap: () async {
_showSessionTerminationDialog(session);
},
child: Padding(
padding: const EdgeInsets.all(16),
2021-11-24 05:40:07 +00:00
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
2021-11-23 19:54:47 +00:00
children: [
2021-11-24 05:40:07 +00:00
_getUAWidget(session),
2022-07-04 06:02:17 +00:00
const Padding(padding: EdgeInsets.all(4)),
2021-11-24 05:40:07 +00:00
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
2021-11-23 19:54:47 +00:00
children: [
2021-11-24 11:31:08 +00:00
Flexible(
child: Text(
session.ip,
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.8),
2021-11-24 11:31:08 +00:00
fontSize: 14,
),
2021-11-24 05:40:07 +00:00
),
),
2022-07-04 06:02:17 +00:00
const Padding(padding: EdgeInsets.all(8)),
2021-11-24 11:31:08 +00:00
Flexible(
child: Text(
getFormattedTime(lastUsedTime),
style: TextStyle(
color: Theme.of(context)
.colorScheme
.onSurface
.withOpacity(0.8),
2021-11-24 11:31:08 +00:00
fontSize: 12,
),
2021-11-23 19:54:47 +00:00
),
),
2021-11-23 19:54:47 +00:00
],
),
],
),
),
2021-11-23 20:10:51 +00:00
),
2022-07-04 06:02:17 +00:00
const Divider(),
2021-11-23 20:10:51 +00:00
],
);
}
2021-11-23 19:54:47 +00:00
Future<void> _terminateSession(Session session) async {
2022-05-17 11:38:21 +00:00
final dialog = createProgressDialog(context, "Please wait...");
2021-11-23 19:54:47 +00:00
await dialog.show();
try {
await UserService.instance.terminateSession(session.token);
await _fetchActiveSessions();
await dialog.hide();
2023-02-03 10:54:38 +00:00
} catch (e) {
await dialog.hide();
2023-02-03 10:54:38 +00:00
_logger.severe('failed to terminate');
showErrorDialog(
2022-06-11 08:23:52 +00:00
context,
2023-04-04 16:56:36 +00:00
S.of(context).oops,
S.of(context).somethingWentWrongPleaseTryAgain,
2022-06-11 08:23:52 +00:00
);
}
2021-11-23 19:54:47 +00:00
}
Future<void> _fetchActiveSessions() async {
2023-02-03 06:49:43 +00:00
_sessions = await UserService.instance.getActiveSessions().onError((e, s) {
_logger.severe("failed to fetch active sessions", e, s);
2023-02-03 10:54:38 +00:00
throw e!;
2021-11-23 20:05:42 +00:00
});
2022-12-28 04:52:25 +00:00
if (_sessions != null) {
_sessions!.sessions.sort((first, second) {
return second.lastUsedTime.compareTo(first.lastUsedTime);
});
2023-02-03 06:49:43 +00:00
if (mounted) {
setState(() {});
}
2022-12-28 04:52:25 +00:00
}
}
2021-11-23 19:54:47 +00:00
void _showSessionTerminationDialog(Session session) {
2021-11-23 20:05:42 +00:00
final isLoggingOutFromThisDevice =
session.token == Configuration.instance.getToken();
Widget text;
if (isLoggingOutFromThisDevice) {
2023-04-04 16:56:36 +00:00
text = Text(
S.of(context).thisWillLogYouOutOfThisDevice,
2021-11-23 20:05:42 +00:00
);
} else {
text = SingleChildScrollView(
child: Column(
children: [
2023-04-04 16:56:36 +00:00
Text(
S.of(context).thisWillLogYouOutOfTheFollowingDevice,
2021-11-23 20:05:42 +00:00
),
2022-07-04 06:02:17 +00:00
const Padding(padding: EdgeInsets.all(8)),
2021-11-23 20:05:42 +00:00
Text(
2021-11-24 05:40:07 +00:00
session.ua,
style: Theme.of(context).textTheme.caption,
2021-11-23 20:05:42 +00:00
),
],
),
);
}
2022-08-29 14:43:31 +00:00
final AlertDialog alert = AlertDialog(
2023-04-04 16:56:36 +00:00
title: Text(S.of(context).terminateSession),
2021-11-23 20:05:42 +00:00
content: text,
2021-11-23 19:54:47 +00:00
actions: [
TextButton(
2023-04-04 16:56:36 +00:00
child: Text(
S.of(context).terminate,
style: const TextStyle(
2021-11-23 19:54:47 +00:00
color: Colors.red,
),
),
onPressed: () async {
Navigator.of(context, rootNavigator: true).pop('dialog');
2021-11-23 20:05:42 +00:00
if (isLoggingOutFromThisDevice) {
await UserService.instance.logout(context);
} else {
_terminateSession(session);
}
2021-11-23 19:54:47 +00:00
},
),
TextButton(
child: Text(
2023-04-04 16:56:36 +00:00
S.of(context).cancel,
2021-11-23 19:54:47 +00:00
style: TextStyle(
2021-11-23 20:05:42 +00:00
color: isLoggingOutFromThisDevice
2022-07-12 06:30:02 +00:00
? Theme.of(context).colorScheme.greenAlternative
: Theme.of(context).colorScheme.defaultTextColor,
2021-11-23 19:54:47 +00:00
),
),
onPressed: () {
Navigator.of(context, rootNavigator: true).pop('dialog');
},
),
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
2021-11-23 20:05:42 +00:00
Widget _getUAWidget(Session session) {
if (session.token == Configuration.instance.getToken()) {
return Text(
2023-04-04 16:56:36 +00:00
S.of(context).thisDevice,
2021-11-23 20:05:42 +00:00
style: TextStyle(
fontWeight: FontWeight.bold,
2022-07-12 06:30:02 +00:00
color: Theme.of(context).colorScheme.greenAlternative,
2021-11-23 20:05:42 +00:00
),
);
}
2021-11-24 05:40:07 +00:00
return Text(session.prettyUA);
}
}