Update landing page to provide an option to update the app's endpoint

This commit is contained in:
vishnukvmd 2024-04-03 17:24:44 +05:30
parent 54c4862e71
commit ee33a3229f
2 changed files with 133 additions and 3 deletions

View file

@ -19,7 +19,10 @@ import 'package:photos/ui/components/buttons/button_widget.dart';
import 'package:photos/ui/components/dialog_widget.dart';
import 'package:photos/ui/components/models/button_type.dart';
import 'package:photos/ui/payment/subscription.dart';
import "package:photos/ui/settings/developer_settings_page.dart";
import "package:photos/ui/settings/developer_settings_widget.dart";
import "package:photos/ui/settings/language_picker.dart";
import "package:photos/utils/dialog_util.dart";
import "package:photos/utils/navigation_util.dart";
class LandingPageWidget extends StatefulWidget {
@ -30,7 +33,10 @@ class LandingPageWidget extends StatefulWidget {
}
class _LandingPageWidgetState extends State<LandingPageWidget> {
static const kDeveloperModeTapCountThreshold = 7;
double _featureIndex = 0;
int _developerModeTapCount = 0;
@override
void initState() {
@ -40,7 +46,35 @@ class _LandingPageWidgetState extends State<LandingPageWidget> {
@override
Widget build(BuildContext context) {
return Scaffold(body: _getBody(), resizeToAvoidBottomInset: false);
return Scaffold(
body: GestureDetector(
onTap: () async {
_developerModeTapCount++;
if (_developerModeTapCount >= kDeveloperModeTapCountThreshold) {
_developerModeTapCount = 0;
final result = await showChoiceDialog(
context,
title: S.of(context).developerSettings,
firstButtonLabel: S.of(context).yes,
body: S.of(context).developerSettingsWarning,
isDismissible: false,
);
if (result?.action == ButtonAction.first) {
await Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) {
return const DeveloperSettingsPage();
},
),
);
setState(() {});
}
}
},
child: _getBody(),
),
resizeToAvoidBottomInset: false,
);
}
Widget _getBody() {
@ -131,6 +165,7 @@ class _LandingPageWidgetState extends State<LandingPageWidget> {
),
),
),
const DeveloperSettingsWidget(),
const Padding(
padding: EdgeInsets.all(20),
),
@ -195,7 +230,9 @@ class _LandingPageWidgetState extends State<LandingPageWidget> {
// No key
if (Configuration.instance.getKeyAttributes() == null) {
// Never had a key
page = const PasswordEntryPage(mode: PasswordEntryMode.set,);
page = const PasswordEntryPage(
mode: PasswordEntryMode.set,
);
} else if (Configuration.instance.getKey() == null) {
// Yet to decrypt the key
page = const PasswordReentryPage();
@ -223,7 +260,9 @@ class _LandingPageWidgetState extends State<LandingPageWidget> {
// No key
if (Configuration.instance.getKeyAttributes() == null) {
// Never had a key
page = const PasswordEntryPage(mode: PasswordEntryMode.set,);
page = const PasswordEntryPage(
mode: PasswordEntryMode.set,
);
} else if (Configuration.instance.getKey() == null) {
// Yet to decrypt the key
page = const PasswordReentryPage();

View file

@ -0,0 +1,91 @@
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import "package:photos/core/configuration.dart";
import "package:photos/core/network/network.dart";
import "package:photos/generated/l10n.dart";
import "package:photos/ui/common/gradient_button.dart";
import "package:photos/utils/dialog_util.dart";
import "package:photos/utils/toast_util.dart";
class DeveloperSettingsPage extends StatefulWidget {
const DeveloperSettingsPage({super.key});
@override
State<DeveloperSettingsPage> createState() => _DeveloperSettingsPageState();
}
class _DeveloperSettingsPageState extends State<DeveloperSettingsPage> {
final _logger = Logger('DeveloperSettingsPage');
final _urlController = TextEditingController();
@override
void dispose() {
_urlController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
_logger.info(
"Current endpoint is: ${Configuration.instance.getHttpEndpoint()}",
);
return Scaffold(
appBar: AppBar(
title: Text(S.of(context).developerSettings),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _urlController,
decoration: InputDecoration(
labelText: S.of(context).serverEndpoint,
hintText: Configuration.instance.getHttpEndpoint(),
),
autofocus: true,
),
const SizedBox(height: 40),
GradientButton(
onTap: () async {
final url = _urlController.text;
_logger.info("Entered endpoint: $url");
try {
final uri = Uri.parse(url);
if ((uri.scheme == "http" || uri.scheme == "https")) {
await _ping(url);
await Configuration.instance.setHttpEndpoint(url);
showToast(context, S.of(context).endpointUpdatedMessage);
Navigator.of(context).pop();
} else {
throw const FormatException();
}
} catch (e) {
// ignore: unawaited_futures
showErrorDialog(
context,
S.of(context).invalidEndpoint,
S.of(context).invalidEndpointMessage,
);
}
},
text: S.of(context).save,
),
],
),
),
);
}
Future<void> _ping(String endpoint) async {
try {
final response =
await NetworkClient.instance.getDio().get('$endpoint/ping');
if (response.data['message'] != 'pong') {
throw Exception('Invalid response');
}
} catch (e) {
throw Exception('Error occurred: $e');
}
}
}