2023-07-10 17:32:14 +02:00
|
|
|
import 'package:flutter/material.dart';
|
2023-07-25 21:14:07 +02:00
|
|
|
import 'package:package_info_plus/package_info_plus.dart';
|
2024-01-27 23:07:06 +01:00
|
|
|
import 'package:shlink_app/API/server_manager.dart';
|
|
|
|
import 'package:shlink_app/views/login_view.dart';
|
|
|
|
import 'package:shlink_app/views/opensource_licenses_view.dart';
|
2023-07-10 17:32:14 +02:00
|
|
|
import 'package:url_launcher/url_launcher.dart';
|
2024-01-27 23:07:06 +01:00
|
|
|
import '../globals.dart' as globals;
|
2023-07-10 17:32:14 +02:00
|
|
|
|
|
|
|
class SettingsView extends StatefulWidget {
|
|
|
|
const SettingsView({super.key});
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<SettingsView> createState() => _SettingsViewState();
|
|
|
|
}
|
|
|
|
|
2024-01-28 00:32:09 +01:00
|
|
|
enum ServerStatus { connected, connecting, disconnected }
|
2023-07-10 17:32:14 +02:00
|
|
|
|
|
|
|
class _SettingsViewState extends State<SettingsView> {
|
2024-01-27 23:07:06 +01:00
|
|
|
var _serverVersion = "---";
|
|
|
|
ServerStatus _serverStatus = ServerStatus.connecting;
|
2024-01-28 00:32:09 +01:00
|
|
|
PackageInfo packageInfo =
|
|
|
|
PackageInfo(appName: "", packageName: "", version: "", buildNumber: "");
|
2023-07-10 17:32:14 +02:00
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
// TODO: implement initState
|
|
|
|
super.initState();
|
2024-01-28 00:32:09 +01:00
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) => getServerHealth());
|
2023-07-10 17:32:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void getServerHealth() async {
|
2024-01-27 23:07:06 +01:00
|
|
|
var packageInfo = await PackageInfo.fromPlatform();
|
2023-07-25 21:14:07 +02:00
|
|
|
setState(() {
|
2024-03-31 21:08:41 +02:00
|
|
|
this.packageInfo = packageInfo;
|
2023-07-25 21:14:07 +02:00
|
|
|
});
|
2023-07-10 17:32:14 +02:00
|
|
|
final response = await globals.serverManager.getServerHealth();
|
|
|
|
response.fold((l) {
|
|
|
|
setState(() {
|
2024-01-27 23:07:06 +01:00
|
|
|
_serverVersion = l.version;
|
|
|
|
_serverStatus = ServerStatus.connected;
|
2023-07-10 17:32:14 +02:00
|
|
|
});
|
|
|
|
}, (r) {
|
|
|
|
setState(() {
|
2024-01-27 23:07:06 +01:00
|
|
|
_serverStatus = ServerStatus.disconnected;
|
2023-07-10 17:32:14 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
var text = "";
|
|
|
|
if (r is RequestFailure) {
|
|
|
|
text = r.description;
|
2024-01-28 00:32:09 +01:00
|
|
|
} else {
|
2023-07-10 17:32:14 +02:00
|
|
|
text = (r as ApiFailure).detail;
|
|
|
|
}
|
|
|
|
|
2024-01-28 00:32:09 +01:00
|
|
|
final snackBar = SnackBar(
|
|
|
|
content: Text(text),
|
|
|
|
backgroundColor: Colors.red[400],
|
|
|
|
behavior: SnackBarBehavior.floating);
|
2023-07-10 17:32:14 +02:00
|
|
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Scaffold(
|
2024-01-28 00:32:09 +01:00
|
|
|
body: CustomScrollView(
|
|
|
|
slivers: [
|
|
|
|
SliverAppBar.medium(
|
|
|
|
expandedHeight: 120,
|
|
|
|
title: const Text(
|
|
|
|
"Settings",
|
|
|
|
style: TextStyle(fontWeight: FontWeight.bold),
|
2023-07-10 17:32:14 +02:00
|
|
|
),
|
2024-01-28 00:32:09 +01:00
|
|
|
actions: [
|
|
|
|
PopupMenuButton(
|
|
|
|
itemBuilder: (context) {
|
|
|
|
return [
|
|
|
|
const PopupMenuItem(
|
|
|
|
value: 0,
|
2024-03-31 21:58:31 +02:00
|
|
|
child: Text("Log out", style: TextStyle(color: Colors.red)),
|
2024-01-28 00:32:09 +01:00
|
|
|
)
|
|
|
|
];
|
|
|
|
},
|
|
|
|
onSelected: (value) {
|
|
|
|
if (value == 0) {
|
|
|
|
globals.serverManager.logOut().then((value) =>
|
|
|
|
Navigator.of(context).pushReplacement(MaterialPageRoute(
|
|
|
|
builder: (context) => const LoginView())));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
SliverToBoxAdapter(
|
|
|
|
child: Padding(
|
2023-07-10 17:32:14 +02:00
|
|
|
padding: const EdgeInsets.all(12.0),
|
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
Container(
|
2024-01-28 00:32:09 +01:00
|
|
|
decoration: BoxDecoration(
|
|
|
|
borderRadius: BorderRadius.circular(8),
|
|
|
|
color: Theme.of(context).brightness == Brightness.light
|
|
|
|
? Colors.grey[100]
|
|
|
|
: Colors.grey[900],
|
|
|
|
),
|
2023-07-10 17:32:14 +02:00
|
|
|
child: Padding(
|
|
|
|
padding: const EdgeInsets.all(12.0),
|
|
|
|
child: Row(
|
|
|
|
children: [
|
2024-01-28 00:32:09 +01:00
|
|
|
Icon(Icons.dns_outlined,
|
|
|
|
color: (() {
|
|
|
|
switch (_serverStatus) {
|
|
|
|
case ServerStatus.connected:
|
|
|
|
return Colors.green;
|
|
|
|
case ServerStatus.connecting:
|
|
|
|
return Colors.orange;
|
|
|
|
case ServerStatus.disconnected:
|
|
|
|
return Colors.red;
|
|
|
|
}
|
|
|
|
}())),
|
2024-01-27 23:07:06 +01:00
|
|
|
const SizedBox(width: 8),
|
2023-07-10 17:32:14 +02:00
|
|
|
Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
2024-01-28 00:32:09 +01:00
|
|
|
const Text("Connected to",
|
|
|
|
style: TextStyle(color: Colors.grey)),
|
|
|
|
Text(globals.serverManager.getServerUrl(),
|
|
|
|
style: const TextStyle(
|
|
|
|
fontWeight: FontWeight.bold,
|
|
|
|
fontSize: 16)),
|
2023-07-10 17:32:14 +02:00
|
|
|
Row(
|
|
|
|
children: [
|
2024-01-28 00:32:09 +01:00
|
|
|
const Text("API Version: ",
|
|
|
|
style: TextStyle(
|
|
|
|
color: Colors.grey,
|
|
|
|
fontWeight: FontWeight.w600)),
|
|
|
|
Text(globals.serverManager.getApiVersion(),
|
|
|
|
style:
|
|
|
|
const TextStyle(color: Colors.grey)),
|
2024-01-27 23:07:06 +01:00
|
|
|
const SizedBox(width: 16),
|
2024-01-28 00:32:09 +01:00
|
|
|
const Text("Server Version: ",
|
|
|
|
style: TextStyle(
|
|
|
|
color: Colors.grey,
|
|
|
|
fontWeight: FontWeight.w600)),
|
|
|
|
Text(_serverVersion,
|
|
|
|
style:
|
|
|
|
const TextStyle(color: Colors.grey))
|
2023-07-10 17:32:14 +02:00
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
2024-01-27 23:07:06 +01:00
|
|
|
const SizedBox(height: 8),
|
|
|
|
const Divider(),
|
|
|
|
const SizedBox(height: 8),
|
2023-07-10 17:32:14 +02:00
|
|
|
GestureDetector(
|
|
|
|
onTap: () {
|
2024-01-28 00:32:09 +01:00
|
|
|
Navigator.of(context).push(MaterialPageRoute(
|
|
|
|
builder: (context) =>
|
|
|
|
const OpenSourceLicensesView()));
|
2023-07-10 17:32:14 +02:00
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
borderRadius: BorderRadius.circular(8),
|
2024-01-28 00:32:09 +01:00
|
|
|
color: Theme.of(context).brightness == Brightness.light
|
|
|
|
? Colors.grey[100]
|
|
|
|
: Colors.grey[900],
|
2023-07-10 17:32:14 +02:00
|
|
|
),
|
2024-01-27 23:07:06 +01:00
|
|
|
child: const Padding(
|
2024-01-28 00:32:09 +01:00
|
|
|
padding: EdgeInsets.only(
|
|
|
|
left: 12, right: 12, top: 20, bottom: 20),
|
2023-07-10 17:32:14 +02:00
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
children: [
|
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
Icon(Icons.policy_outlined),
|
|
|
|
SizedBox(width: 8),
|
2024-01-28 00:32:09 +01:00
|
|
|
Text("Open Source Licenses",
|
|
|
|
style: TextStyle(
|
|
|
|
fontWeight: FontWeight.w500)),
|
2023-07-10 17:32:14 +02:00
|
|
|
],
|
|
|
|
),
|
|
|
|
Icon(Icons.chevron_right)
|
2024-01-28 00:32:09 +01:00
|
|
|
]),
|
2023-07-10 17:32:14 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
2024-01-27 23:07:06 +01:00
|
|
|
const SizedBox(height: 16),
|
2023-07-10 17:32:14 +02:00
|
|
|
GestureDetector(
|
|
|
|
onTap: () async {
|
2024-01-28 00:32:09 +01:00
|
|
|
var url = Uri.parse(
|
|
|
|
"https://github.com/rainloreley/shlink-mobile-app");
|
2023-07-10 17:32:14 +02:00
|
|
|
if (await canLaunchUrl(url)) {
|
2024-01-28 00:32:09 +01:00
|
|
|
launchUrl(url, mode: LaunchMode.externalApplication);
|
2023-07-10 17:32:14 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
borderRadius: BorderRadius.circular(8),
|
2024-01-28 00:32:09 +01:00
|
|
|
color: Theme.of(context).brightness == Brightness.light
|
|
|
|
? Colors.grey[100]
|
|
|
|
: Colors.grey[900],
|
2023-07-10 17:32:14 +02:00
|
|
|
),
|
2024-01-27 23:07:06 +01:00
|
|
|
child: const Padding(
|
2024-01-28 00:32:09 +01:00
|
|
|
padding: EdgeInsets.only(
|
|
|
|
left: 12, right: 12, top: 20, bottom: 20),
|
2023-07-10 17:32:14 +02:00
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
children: [
|
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
Icon(Icons.code),
|
|
|
|
SizedBox(width: 8),
|
2024-01-28 00:32:09 +01:00
|
|
|
Text("GitHub",
|
|
|
|
style: TextStyle(
|
|
|
|
fontWeight: FontWeight.w500)),
|
2023-07-10 17:32:14 +02:00
|
|
|
],
|
|
|
|
),
|
|
|
|
Icon(Icons.chevron_right)
|
2024-01-28 00:32:09 +01:00
|
|
|
]),
|
2023-07-10 17:32:14 +02:00
|
|
|
),
|
|
|
|
),
|
2023-07-25 21:14:07 +02:00
|
|
|
),
|
2024-01-27 23:07:06 +01:00
|
|
|
const SizedBox(height: 16),
|
2023-07-25 21:14:07 +02:00
|
|
|
GestureDetector(
|
|
|
|
onTap: () async {
|
2024-01-28 00:32:09 +01:00
|
|
|
var url = Uri.parse(
|
2024-02-23 16:33:00 +01:00
|
|
|
"https://wiki.abmgrt.dev/de/projects/shlink-manager/privacy");
|
2023-07-25 21:14:07 +02:00
|
|
|
if (await canLaunchUrl(url)) {
|
|
|
|
launchUrl(url, mode: LaunchMode.externalApplication);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
borderRadius: BorderRadius.circular(8),
|
2024-01-28 00:32:09 +01:00
|
|
|
color: Theme.of(context).brightness == Brightness.light
|
|
|
|
? Colors.grey[100]
|
|
|
|
: Colors.grey[900],
|
2023-07-25 21:14:07 +02:00
|
|
|
),
|
2024-01-27 23:07:06 +01:00
|
|
|
child: const Padding(
|
2024-01-28 00:32:09 +01:00
|
|
|
padding: EdgeInsets.only(
|
|
|
|
left: 12, right: 12, top: 20, bottom: 20),
|
2023-07-25 21:14:07 +02:00
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
|
|
children: [
|
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
Icon(Icons.lock),
|
|
|
|
SizedBox(width: 8),
|
2024-01-28 00:32:09 +01:00
|
|
|
Text("Privacy Policy",
|
|
|
|
style: TextStyle(
|
|
|
|
fontWeight: FontWeight.w500)),
|
2023-07-25 21:14:07 +02:00
|
|
|
],
|
|
|
|
),
|
|
|
|
Icon(Icons.chevron_right)
|
2024-01-28 00:32:09 +01:00
|
|
|
]),
|
2023-07-25 21:14:07 +02:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
2024-01-27 23:07:06 +01:00
|
|
|
const SizedBox(height: 16),
|
|
|
|
if (packageInfo.appName != "")
|
2023-07-25 21:14:07 +02:00
|
|
|
Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
|
|
children: [
|
2024-03-31 21:08:41 +02:00
|
|
|
Container(
|
|
|
|
padding: const EdgeInsets.only(
|
2024-03-31 21:58:31 +02:00
|
|
|
left: 8, right: 8, top: 4, bottom: 4),
|
2024-03-31 21:08:41 +02:00
|
|
|
decoration: BoxDecoration(
|
|
|
|
borderRadius: BorderRadius.circular(8),
|
2024-03-31 21:58:31 +02:00
|
|
|
color:
|
|
|
|
Theme.of(context).brightness == Brightness.light
|
|
|
|
? Colors.grey[100]
|
|
|
|
: Colors.grey[900],
|
2024-03-31 21:08:41 +02:00
|
|
|
),
|
|
|
|
child: Text(
|
|
|
|
"${packageInfo.appName}, v${packageInfo.version} (${packageInfo.buildNumber})",
|
|
|
|
style: const TextStyle(color: Colors.grey),
|
|
|
|
),
|
|
|
|
)
|
2024-01-28 00:32:09 +01:00
|
|
|
],
|
2023-07-25 21:14:07 +02:00
|
|
|
)
|
2023-07-10 17:32:14 +02:00
|
|
|
],
|
2024-01-28 00:32:09 +01:00
|
|
|
)),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
));
|
2023-07-10 17:32:14 +02:00
|
|
|
}
|
|
|
|
}
|