Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to change backend URL on the setting page #54

Merged
merged 25 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions lib/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import 'dart:convert';
import 'dart:io';

class Client {
static final protocol = 'https';
static final domain = 'api.anypayx.com';
static final host = "$protocol://$domain";
static Uri apiUri = Uri(scheme: 'https', path: 'api.anypayx.com');

static String humanize(String str) {
return StringUtils.capitalize(str);
Expand Down Expand Up @@ -132,7 +130,7 @@ class Client {

var response = await makeRequest('get',
unauthorized: (() => Authentication.logout()),
uri: Uri.https(domain, '/invoices', {
uri: Uri.https(apiUri.path, '/invoices', {
'limit': perPage.toString(),
'offset': offset.toString(),
'complete': 'true',
Expand Down Expand Up @@ -192,7 +190,7 @@ class Client {

static Future<Map<dynamic, dynamic>> makeRequest(method, {path, uri, headers, body, requireAuth, basicAuth, unauthorized, genericErrorCodes}) async {
try {
http.Request request = http.Request(method, uri ?? Uri.parse('$host$path'));
http.Request request = http.Request(method, uri ?? Uri.parse('${apiUri.toString()}$path'));
if (requireAuth ?? false) request.headers['authorization'] = buildAuthHeader();
if (basicAuth != null) request.headers['authorization'] = basicAuth;
if (genericErrorCodes == null) genericErrorCodes = [500];
Expand Down Expand Up @@ -238,4 +236,8 @@ class Client {
};
}
}

static updateUri({required Uri uri}) {
apiUri = uri;
}
}
31 changes: 28 additions & 3 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:app/app_controller.dart';
import 'package:app/router.dart';
import 'client.dart';
import 'native_storage.dart';

void main() {
WidgetsFlutterBinding.ensureInitialized();
setDefaultUrl();
Authentication.checkForAuth().then((isAuthenticated) {
AnyFluroRouter.setupRouter();
runApp(Anypay(isAuthenticated));
Expand Down Expand Up @@ -35,11 +38,18 @@ class Anypay extends StatelessWidget {
colorScheme: ColorScheme.fromSwatch().copyWith(
background: AppController.white,
secondary: AppController.blue,
brightness: Brightness.light
brightness: Brightness.light),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Colors.black,
), //button color
foregroundColor: MaterialStateProperty.all<Color>(
Colors.white), //text (and icon)
),
),
fontFamily: 'Ubuntu',
);

var darkTheme = ThemeData(
primaryColorDark: Color(0xffCCCCCC),
primaryColorLight: Color(0xFFFFFFFF),
Expand All @@ -55,7 +65,15 @@ class Anypay extends StatelessWidget {
colorScheme: ColorScheme.fromSwatch().copyWith(
background: Color(0xff222222),
secondary: Color(0xff2196f3),
brightness: Brightness.dark
brightness: Brightness.dark),
elevatedButtonTheme: ElevatedButtonThemeData(
pshenmic marked this conversation as resolved.
Show resolved Hide resolved
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
Colors.white,
), //button color
foregroundColor: MaterialStateProperty.all<Color>(
Colors.black), //text (and icon)
),
),
fontFamily: 'Ubuntu',
);
Expand Down Expand Up @@ -87,3 +105,10 @@ class Anypay extends StatelessWidget {
});
}
}

void setDefaultUrl() async {
final storedUrl = await Storage.read("backend_url");
if (storedUrl != null) {
Client.updateUri(uri: Uri.parse(storedUrl));
}
}
4 changes: 2 additions & 2 deletions lib/models/invoice.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class Invoice {

String urlStyleUri([useCurrency]) {
useCurrency = useCurrency ?? currency;
String host = Client.host;
String host = Client.apiUri.toString();
String protocol = {
'BTC': 'bitcoin',
'BCH': 'bitcoincash',
Expand All @@ -143,7 +143,7 @@ class Invoice {
}

String uriFor(currency, {format}) {
if (format == 'pay') return "pay:?r=${Client.host}/r/$uid";
if (format == 'pay') return "pay:?r=${Client.apiUri.toString()}/r/$uid";
if (format == 'url') return urlStyleUri(currency);

return paymentOptionFor(currency)['uri'];
Expand Down
6 changes: 6 additions & 0 deletions lib/router.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:app/routes/edit_backend_url.dart';
import 'package:flutter/material.dart';
import 'package:fluro/fluro.dart';

Expand Down Expand Up @@ -84,6 +85,11 @@ class AnyFluroRouter {
handler: newHandler(() => SetCurrency(), []),
transitionType: TransitionType.inFromBottom,
);
router.define(
'settings/backend_url',
handler: newHandler(() => EditBackEndUrl(), []),
transitionType: TransitionType.inFromBottom,
);
router.define(
'settings/addresses',
handler: newHandler(() => Addresses(), []),
Expand Down
158 changes: 158 additions & 0 deletions lib/routes/edit_backend_url.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import 'package:app/authentication.dart';
import 'package:flutter/material.dart';
import 'package:app/back_button.dart';
import 'package:app/app_controller.dart';
import 'package:app/currencies.dart';
import '../client.dart';
import '../native_storage.dart';

class EditBackEndUrl extends StatelessWidget {
@override
Widget build(BuildContext context) {
return EditBackEndUrlPage(title: "Edit Backend Url");
}
}

class EditBackEndUrlPage extends StatefulWidget {
EditBackEndUrlPage({Key? key, required this.title}) : super(key: key);

final String title;

@override
_EditBackEndUrlState createState() => _EditBackEndUrlState();
}

class _EditBackEndUrlState extends State<EditBackEndUrlPage> {
var _successMessage = '';
pshenmic marked this conversation as resolved.
Show resolved Hide resolved

var denomination;

var symbol;

var urlController = TextEditingController();

GlobalKey<FormState> _formKey = GlobalKey();


@override
void initState() {
super.initState();
setBackendUrl();
}

void setBackendUrl() {
urlController.text = Client.apiUri.toString();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_successMessage,
style: TextStyle(color: AppController.green),
),
Container(
width: 300,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_EditUrlLink(),
CircleBackButton(
margin: EdgeInsets.only(top: 20.0),
backPath: 'navigation',
),
],
)),
],
),
),
),
);
}

Widget _EditUrlLink() {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
controller: urlController,
decoration: InputDecoration(
labelText: 'Update Backend Url',
pshenmic marked this conversation as resolved.
Show resolved Hide resolved
hintText: "http:// or https://"),
validator: (value) {
if (value != null && Uri.parse(value).isAbsolute) {
return null;
} else {
return "Please provide valid url";
}
}),
Container(
margin: EdgeInsets.only(top: 40.0),
child: GestureDetector(
child: Text('SAVE', style: TextStyle(
fontWeight: FontWeight.bold,
color: AppController.blue,
fontSize: 18,
)),
onTap: () async {
if (_formKey.currentState!.validate()) {
showAlertDialog(
context: context,
title: "Confirmation",
desc: "Are you sure you want to change the backend API url?",
onOkPressed: () async {
await Storage.write(
"backend_url", urlController.text);
Client.updateUri(
uri: Uri.parse(urlController.text));
Authentication.logout();
});
}
},
),
),
],
),
);
}
showAlertDialog(
{required BuildContext context,
required String title,
required String desc,
required onOkPressed}) {
Widget okButton = TextButton(
child: Text("OK"),
onPressed: onOkPressed,
);
Widget cancelButton = TextButton(
child: Text("Cancel"),
onPressed: () {
Navigator.pop(context);
},
);
AlertDialog alert = AlertDialog(
title: Text(title,
style: TextStyle(
pshenmic marked this conversation as resolved.
Show resolved Hide resolved
color:
AppController.enableDarkMode ? Colors.white : Colors.black)),
content: Text(desc),
actions: [
cancelButton,
okButton,
],
);
showDialog(
context: context,
builder: (BuildContext context) {
return alert;
},
);
}
}
29 changes: 27 additions & 2 deletions lib/routes/login.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:convert';

import 'package:email_validator/email_validator.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:app/app_controller.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -68,6 +69,13 @@ class _LoginPageState extends State<LoginPage> {
});
Client.authenticate(email.text, password.text).then((response) {
_submitting = false;
if (response['body'] == null || response['body'].isEmpty) {
setState(() {
_errorMessage =
"An unknown error occured, try changing the backend url.";
});
return;
}
if (response['success']) {
AppController.closeUntilPath('/new-invoice');
}
Expand Down Expand Up @@ -141,7 +149,7 @@ class _LoginPageState extends State<LoginPage> {
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(bottom: _submitting ? 20.0 : 40.0),
margin: EdgeInsets.only(bottom: 20.0),
child: _submitting ?
SpinKitCircle(color: AppController.blue) :
GestureDetector(
Expand Down Expand Up @@ -183,9 +191,26 @@ class _LoginPageState extends State<LoginPage> {
]
),
),
Container(
margin: EdgeInsets.only(top: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
child: Text('Settings', style: TextStyle(
fontWeight: FontWeight.bold,
color: AppController.blue,
fontSize: 18,
)),
onTap: () {
Navigator.pushNamed(context, 'settings');
}
),
]
),
),
],
),
);
}

}
Loading
Loading