diff --git a/.env b/.env deleted file mode 100644 index ba7db22..0000000 --- a/.env +++ /dev/null @@ -1 +0,0 @@ -SOFTPLAYER_BACKEND_URL=https://softplayer-backend.badhouseplants.net:8080 diff --git a/Containerfile b/Containerfile index f50acb0..b7e28ec 100644 --- a/Containerfile +++ b/Containerfile @@ -1,4 +1,7 @@ +# Environemnt to install flutter and build web FROM debian:latest AS build-env + +# install all needed stuff RUN apt-get update RUN apt-get install -y curl tar xz-utils git @@ -10,12 +13,13 @@ ARG APP=/app/ RUN curl -l -o /tmp/flutter.tar.xz https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz RUN tar -xf /tmp/flutter.tar.xz -C /usr/local + ENV PATH="$FLUTTER_SDK/bin:$FLUTTER_SDK/bin/cache/dart-sdk/bin:${PATH}" -WORKDIR $APP +RUN mkdir $APP COPY . $APP - -RUN flutter build web --release +WORKDIR $APP +RUN flutter build web # once heare the app will be compiled and ready to deploy diff --git a/Makefile b/Makefile index 9c84173..4ec35f6 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,3 @@ format: dart format $$(find . -type f -name '*.dart') fix: dart fix ./lib --apply - -serve: - flutter run -d web-server --web-port 8080 diff --git a/assets/login_background.jpg b/assets/login_background.jpg deleted file mode 100644 index d74468e..0000000 Binary files a/assets/login_background.jpg and /dev/null differ diff --git a/assets/main_background.jpg b/assets/main_background.jpg deleted file mode 100644 index 8d0f09f..0000000 Binary files a/assets/main_background.jpg and /dev/null differ diff --git a/lib/api/grpc/accounts.dart b/lib/api/grpc/accounts.dart index 0fb6882..4659d94 100644 --- a/lib/api/grpc/accounts.dart +++ b/lib/api/grpc/accounts.dart @@ -1,4 +1,6 @@ + import 'package:grpc/grpc_web.dart'; +import 'package:softplayer_dart_proto/accounts/accounts_v1.pbgrpc.dart'; import 'package:softplayer_dart_proto/main.dart'; class AccountLocalData { @@ -9,7 +11,6 @@ class AccountLocalData { String uuid; String token; } - class AccountsGrpc { final GrpcWebClientChannel channel; late AccountsClient accountsStub; @@ -21,8 +22,7 @@ class AccountsGrpc { accountsStub = AccountsClient(channel); } - Future signIn( - String username, String email, String password) async { + Future signIn(String username, String email, String password) async { final request = AccountWithPassword( data: AccountData( name: username, @@ -39,8 +39,7 @@ class AccountsGrpc { } } - Future signUp( - String username, String email, String password) async { + Future signUp(String username, String email, String password) async { final request = AccountWithPassword( data: AccountData( name: username, @@ -56,33 +55,4 @@ class AccountsGrpc { rethrow; } } - - Future resetPassword(String username, String email) async { - final request = AccountData( - name: username, - email: email, - ); - try { - final response = await accountsStub.resetPassword(request); - return response; - } catch (e) { - rethrow; - } - } - - Future newPassword( - String username, String code, String newPassword) async { - final request = AccountWithPasswordAndCode( - data: AccountData( - name: username, - ), - code: code, - password: AccountPassword(password: newPassword)); - try { - final response = await accountsStub.newPassword(request); - return response; - } catch (e) { - rethrow; - } - } } diff --git a/lib/api/grpc/creds.dart b/lib/api/grpc/creds.dart deleted file mode 100644 index c4660e8..0000000 --- a/lib/api/grpc/creds.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'dart:html'; - -class SoftplayerCreds { - final String uuid; - final String token; - - SoftplayerCreds({ - required this.token, - required this.uuid, - }); -} - -class SoftplayerCredsHelpers { - String localStorageEntry(String key) => window.localStorage[key]!; - SoftplayerCreds fromLocalStorage() => SoftplayerCreds( - token: localStorageEntry("token"), uuid: localStorageEntry("uuid")); - void cleanupLocalStorate() { - window.localStorage.remove("token"); - window.localStorage.remove("uuid"); - } -} diff --git a/lib/api/grpc/environments.dart b/lib/api/grpc/environments.dart deleted file mode 100644 index 136d911..0000000 --- a/lib/api/grpc/environments.dart +++ /dev/null @@ -1,106 +0,0 @@ -import 'package:softplayer_dart_proto/main.dart'; -import 'package:softplayer_web/api/grpc/creds.dart'; - -class EnvironmentLocalData { - EnvironmentLocalData( - {required this.serverType, - required this.serverLocation, - required this.provider, - required this.name, - required this.description, - this.uuid}); - - final String name; - final String description; - final String provider; - final String serverType; - final String serverLocation; - String? uuid; -} - -class EnvironmentsGrpc { - // final GrpcWebClientChannel channel; - final EnvironmentsClient envStub; - - // Init the grpc channel for environments - EnvironmentsGrpc(channel) : envStub = EnvironmentsClient(channel); - - // Get environments from the API - Future get(String uuid, SoftplayerCreds creds) async { - final request = GetOptions( - id: EnvironmentId(uuid: uuid), - ownerId: OwnerId(uuid: creds.uuid), - token: Token(token: creds.token), - ); - - try { - final response = await envStub.get(request); - return EnvironmentLocalData( - uuid: uuid, - serverType: response.spec.serverType.toString(), - serverLocation: response.spec.serverLocation.toString(), - provider: response.spec.provider.toString(), - name: response.metadata.name, - description: response.metadata.description); - } catch (e) { - rethrow; - } - } - - Future create( - EnvironmentLocalData data, SoftplayerCreds creds) async { - print(data); - final request = CreateOptions( - metadata: - EnvironmentMetadata(description: data.description, name: data.name), - spec: EnvironmentSpec( - // Currently we do not support other kinds - kubernetes: Kubernetes.KUBERNETES_K3S, - // Currently we do not support other providers - provider: Provider.PROVIDER_HETZNER, - serverLocation: Location.values - .firstWhere((e) => e.toString() == data.serverLocation), - serverType: ServerType.values - .firstWhere((e) => e.toString() == data.serverType), - ), - ownerId: OwnerId(uuid: creds.uuid), - token: Token(token: creds.token), - ); - try { - final response = await envStub.create(request); - return EnvironmentLocalData( - uuid: response.id.uuid, - serverType: response.spec.serverType.toString(), - serverLocation: response.spec.serverLocation.toString(), - provider: response.spec.provider.toString(), - name: response.metadata.name, - description: response.metadata.description); - } catch (e) { - rethrow; - } - } - - Stream> list(SoftplayerCreds creds) async* { - List envs = []; - try { - await for (var feature in envStub.list( - ListOptions( - ownerId: OwnerId(uuid: creds.uuid), - token: Token(token: creds.token), - ), - )) { - envs.add(EnvironmentLocalData( - uuid: feature.id.uuid, - serverType: feature.spec.serverType.toString(), - serverLocation: feature.spec.serverLocation.toString(), - provider: feature.spec.provider.toString(), - name: feature.metadata.name, - description: feature.metadata.description, - )); - } - } catch (e) { - rethrow; - } - yield envs; - } -} diff --git a/lib/components/catalog_card.dart b/lib/components/catalog_card.dart new file mode 100644 index 0000000..8f0469e --- /dev/null +++ b/lib/components/catalog_card.dart @@ -0,0 +1,49 @@ +import 'package:flutter/material.dart'; +import 'package:softplayer_web/models/catalog_entry.dart'; + +class CatalogCard extends StatelessWidget { + const CatalogCard({ + super.key, + required this.data, + }); + final List data; + + List createCards(List data) { + List createCards = []; + for (var app in data) { + createCards.add(Card( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListTile( + //leading: Image.network(app.logoUrl), + leading: const Icon(Icons.nfc), + title: Text(app.name), + subtitle: Text(app.description), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + child: const Text('INSTALL'), + onPressed: () { + print("installing"); + }, + ), + const SizedBox(width: 8), + ], + ), + ], + ), + )); + } + return createCards; + } + + @override + Widget build(BuildContext context) { + return Column( + children: createCards(data), + ); + } +} diff --git a/lib/components/create_env_form.dart b/lib/components/create_env_form.dart deleted file mode 100644 index 09acd4d..0000000 --- a/lib/components/create_env_form.dart +++ /dev/null @@ -1,161 +0,0 @@ -import 'dart:js' as js; -import 'package:flutter/material.dart'; -import 'package:grpc/grpc_web.dart'; -import 'package:softplayer_dart_proto/main.dart'; -import 'package:softplayer_web/api/grpc/creds.dart'; -import 'package:softplayer_web/api/grpc/environments.dart'; -import 'package:softplayer_web/helpers/providers/common.dart' as helper; - -class CreateEnvForm extends StatefulWidget { - CreateEnvForm(GrpcWebClientChannel channel, {super.key}) - : environmentsGrpc = EnvironmentsGrpc(channel); - final EnvironmentsGrpc environmentsGrpc; - - @override - State createState() => _CreateEnvFormState(); -} - -class _CreateEnvFormState extends State { - final _formKey = GlobalKey(); - final String defaultProvider = Provider.PROVIDER_HETZNER.toString(); - late helper.Provider provider = - helper.ProviderHelper().getProvider(defaultProvider); - late String defaultLocation = provider.defaultLocation(); - final nameCtl = TextEditingController(); - final descriptionCtl = TextEditingController(); - late String? serverLocation = defaultLocation; - late String? serverType = ServerType.SERVER_TYPE_REGULAR.toString(); - - void createEnvironment() { - // Validate returns true if the form is valid, or false otherwise. - if (_formKey.currentState!.validate()) { - final name = nameCtl.text; - final description = descriptionCtl.text; - widget.environmentsGrpc - .create( - EnvironmentLocalData( - serverType: serverType!, - serverLocation: serverLocation!, - provider: defaultProvider, - name: name, - description: description), - SoftplayerCredsHelpers().fromLocalStorage()) - .then((rs) { - Navigator.pop(context); - }).catchError((e) { - GrpcError error = e; - String msg; - if (error.message != null) { - msg = error.message!; - } else { - msg = error.toString(); - } - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(msg), - backgroundColor: Colors.red, - showCloseIcon: true, - behavior: SnackBarBehavior.floating, - )); - }); - } - } - - String defaultServerType = "Regular"; - Widget createEnvForm() => SingleChildScrollView( - child: SizedBox( - width: 420, - child: Form( - key: _formKey, - child: Center( - child: Column(children: [ - TextFormField( - autofocus: true, - controller: nameCtl, - decoration: const InputDecoration( - hintText: "Enter the environment name", - icon: Icon(Icons.computer), - label: Text("Name"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextFormField( - autofocus: false, - controller: descriptionCtl, - decoration: const InputDecoration( - hintText: "Enter the environment description", - icon: Icon(Icons.description), - label: Text("Description"), - ), - maxLength: 360, - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - DropdownButtonFormField( - decoration: const InputDecoration( - hintText: "Enter the environment description", - icon: Icon(Icons.computer), - label: Text("Type of the server"), - ), - value: ServerType.SERVER_TYPE_REGULAR.toString(), - isDense: true, - items: ServerType.values - .where((element) => - element != ServerType.SERVER_TYPE_CUSTOM && - element != ServerType.SERVER_TYPE_UNSPECIFIED) - .map((serverType) { - return DropdownMenuItem( - value: serverType.toString(), - child: Text(helper.ProviderHelper() - .getServerType(serverType.toString())), - ); - }).toList(), - onChanged: (value) => setState(() { - serverType = value; - }), - ), - TextButton( - onPressed: () => js.context.callMethod( - 'open', ['https://stackoverflow.com/questions/ask']), - child: const Text("Read more about environment types here"), - ), - DropdownButtonFormField( - decoration: const InputDecoration( - hintText: "Enter the environment location", - icon: Icon(Icons.location_on), - label: Text("Location of the server"), - ), - value: defaultLocation, - isDense: true, - items: Location.values - .where((element) => element - .toString() - .contains(provider.getProviderName().toUpperCase())) - .map((serverType) { - return DropdownMenuItem( - value: serverType.toString(), - child: Text( - provider.getServerLocation(serverType.toString())), - ); - }).toList(), - onChanged: (value) => setState(() { - serverLocation = value; - }), - ), - ]))))); - List createEnvActions() => [ - TextButton( - onPressed: createEnvironment, - child: const Text('OK'), - ), - ]; - - @override - Widget build(BuildContext context) => AlertDialog( - title: const Text("Create a new environment"), - content: createEnvForm(), - actions: createEnvActions(), - ); -} diff --git a/lib/components/environment_card.dart b/lib/components/environment_card.dart deleted file mode 100644 index bfcf857..0000000 --- a/lib/components/environment_card.dart +++ /dev/null @@ -1,102 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:softplayer_web/api/grpc/environments.dart'; -import 'package:softplayer_web/components/environment_preview.dart'; -import 'package:softplayer_web/helpers/providers/common.dart'; - -class EnvirnomentCard extends StatefulWidget { - final EnvironmentLocalData env; - - const EnvirnomentCard({ - super.key, - required this.env, - }); - - @override - State createState() => _EnvirnomentCardState(); -} - -class _EnvirnomentCardState extends State { - late double elevation = 1.0; - - @override - Widget build(BuildContext context) { - Provider provider = ProviderHelper().getProvider(widget.env.provider); - - String serverType; - String serverLocation; - try { - serverType = ProviderHelper().getServerType(widget.env.serverType); - serverLocation = provider.getServerLocation(widget.env.serverLocation); - } catch (e) { - rethrow; - } - - return Container( - margin: const EdgeInsets.all(8.0), - height: 10, - child: MouseRegion( - onExit: (event) { - setState(() { - elevation = 1.0; - }); - }, - onEnter: (event) { - setState(() { - elevation = 5.0; - }); - }, - child: Card( - elevation: elevation, - child: SelectionArea( - child: InkWell( - onLongPress: () => showMenu( - position: RelativeRect.fromSize(Rect.largest, Size.infinite), - context: context, - items: [ - const PopupMenuItem(child: Text("test")), - const PopupMenuItem(child: Text("text")), - ], - ), - onTap: () => showDialog( - context: context, - builder: (context) => EnvirnomentPreiview(env: widget.env), - ), - child: Column( - children: [ - Text(widget.env.name), - const Divider(), - Table( - border: const TableBorder( - bottom: BorderSide.none, - left: BorderSide.none, - right: BorderSide.none, - top: BorderSide.none, - ), - children: [ - TableRow(children: [ - const Text("Description"), - Text(widget.env.description), - ]), - TableRow(children: [ - const Text("Provider"), - Text(provider.getProviderName()), - ]), - TableRow(children: [ - const Text("Server Type"), - Text(serverType), - ]), - TableRow(children: [ - const Text("Location"), - Text(serverLocation), - ]), - ], - ) - ], - ), - ), - ), - ), - ), - ); - } -} diff --git a/lib/components/environment_preview.dart b/lib/components/environment_preview.dart deleted file mode 100644 index 685a453..0000000 --- a/lib/components/environment_preview.dart +++ /dev/null @@ -1,90 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:softplayer_web/api/grpc/environments.dart'; -import 'package:softplayer_web/helpers/providers/common.dart'; - -class EnvirnomentPreiview extends StatefulWidget { - @override - State createState() => _EnvirnomentPreviewState(); - final EnvironmentLocalData env; - - const EnvirnomentPreiview({ - super.key, - required this.env, - }); -} - -class _EnvirnomentPreviewState extends State { - @override - Widget build(BuildContext context) { - Provider provider = ProviderHelper().getProvider(widget.env.provider); - - String serverType; - String serverLocation; - try { - serverType = ProviderHelper().getServerType(widget.env.serverType); - serverLocation = provider.getServerLocation(widget.env.serverLocation); - } catch (e) { - rethrow; - } - - return AlertDialog( - title: Text(widget.env.name), - content: SizedBox( - height: 420, - width: 420, - child: Column( - children: [ - Table( - border: const TableBorder( - bottom: BorderSide.none, - left: BorderSide.none, - right: BorderSide.none, - top: BorderSide.none, - ), - children: [ - TableRow(children: [ - const Text("Description"), - Text(widget.env.description), - ]), - TableRow(children: [ - const Text("Provider"), - Text(provider.getProviderName()), - ]), - TableRow(children: [ - const Text("Server Type"), - Text(serverType), - ]), - TableRow(children: [ - const Text("Location"), - Text(serverLocation), - ]), - ], - ), - const Divider(), - Table( - border: const TableBorder( - bottom: BorderSide.none, - left: BorderSide.none, - right: BorderSide.none, - top: BorderSide.none, - ), - children: const [ - TableRow(children: [ - Text("Price per hour"), - Text("0.52"), - ]), - TableRow(children: [ - Text("Current usage"), - Text("10.5"), - ]), - ], - ), - ], - ), - ), - actions: [ - TextButton(onPressed: () => print("lala"), child: const Text("test")), - TextButton(onPressed: () => print("lala"), child: const Text("test")), - ]); - } -} diff --git a/lib/components/environments.dart b/lib/components/environments.dart deleted file mode 100644 index 25a6686..0000000 --- a/lib/components/environments.dart +++ /dev/null @@ -1,105 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:grpc/grpc_web.dart'; -import 'package:softplayer_web/api/grpc/creds.dart'; -import 'package:softplayer_web/api/grpc/environments.dart'; -import 'package:softplayer_web/components/environment_card.dart'; - -class EnvirnomentList extends StatefulWidget { - const EnvirnomentList({ - super.key, - required this.channel, - }); - final GrpcWebClientChannel channel; - @override - State createState() => _EnvirnomentListState(); -} - -class _EnvirnomentListState extends State { - late EnvironmentsGrpc envGrpc; - List envs = []; - @override - void initState() { - super.initState(); - envGrpc = EnvironmentsGrpc(widget.channel); - } - - final GlobalKey _key = GlobalKey(); // Create a key - - @override - Widget build(BuildContext context) { - return Scaffold( - key: _key, - endDrawer: const Drawer(child: Text("Env")), - body: Container( - width: double.infinity, - height: double.infinity, - decoration: const BoxDecoration( - gradient: LinearGradient(colors: [ - Colors.blueGrey, - Colors.cyan, - Colors.yellow, - ])), - child: StreamBuilder( - stream: - envGrpc.list(SoftplayerCredsHelpers().fromLocalStorage()), - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return const CircularProgressIndicator(); - } else if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.hasError) { - return const Text('Error!'); - } else { - if (snapshot.hasData) { - var data = snapshot.requireData; - if (data.isNotEmpty) { - return Container( - margin: const EdgeInsetsDirectional.fromSTEB( - 50.0, 20.0, 50.0, 10.0), - child: Column(children: [ - Flexible( - child: Container( - child: const TextField( - decoration: InputDecoration( - fillColor: Colors.white, - filled: true, - labelText: "Search", - prefixIcon: Icon(Icons.search)), - ), - ), - ), - Container( - child: Flexible( - child: GridView.count( - childAspectRatio: (30 / 13), - crossAxisCount: 4, - children: snapshot.data! - .map((e) => EnvirnomentCard( - env: e, - )) - .toList(), - )), - ) - ]), - ); - } else { - return Center( - child: Container( - height: 300, - decoration: BoxDecoration( - border: Border.all(), - shape: BoxShape.rectangle, - borderRadius: - const BorderRadius.all(Radius.circular(10)), - color: const Color.fromRGBO(100, 150, 80, 20), - ), - child: const Text( - "To get strated, use the button in the corner"), - )); - } - } - } - } - return const Text("err"); - }))); - } -} diff --git a/lib/components/login_form.dart b/lib/components/login_form.dart deleted file mode 100644 index f909198..0000000 --- a/lib/components/login_form.dart +++ /dev/null @@ -1,403 +0,0 @@ -import 'dart:html'; - -import 'package:flutter/material.dart'; -import 'package:grpc/grpc_web.dart'; -import 'package:softplayer_web/api/grpc/accounts.dart'; - -class LoginForm extends StatefulWidget { - const LoginForm({ - super.key, - required this.grpcChannel, - required this.notifyParent, - }); - final Function() notifyParent; - final GrpcWebClientChannel grpcChannel; - @override - State createState() => _LoginFormState(); -} - -enum Action { singIn, signUp, resetPassword } - -class _LoginFormState extends State { - final _formKey = GlobalKey(); - - final usernameCtrl = TextEditingController(); - final passwordCtrl = TextEditingController(); - final passwordVerifyCtrl = TextEditingController(); - final emailCtrl = TextEditingController(); - final codeCtrl = TextEditingController(); - - late AccountsGrpc accountsGrpc; - Action action = Action.singIn; - bool codeEnabled = false; - static const dialogName = "Login"; - - void submitSignUp() { - // Validate returns true if the form is valid, or false otherwise. - if (_formKey.currentState!.validate()) { - final username = usernameCtrl.text; - final password = passwordCtrl.text; - final email = emailCtrl.text; - accountsGrpc.signUp(username, email, password).then((rs) { - window.localStorage["token"] = rs.token; - window.localStorage["uuid"] = rs.uuid; - widget.notifyParent(); - Navigator.of(context, rootNavigator: true).pop(); - }).catchError((e) { - GrpcError error = e; - String msg; - if (error.message != null) { - msg = error.message!; - } else { - msg = error.toString(); - } - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(msg), - backgroundColor: Colors.red, - showCloseIcon: true, - behavior: SnackBarBehavior.floating, - )); - passwordCtrl.clear(); - }); - } - } - - void submitSignIn() { - // Validate returns true if the form is valid, or false otherwise. - if (_formKey.currentState!.validate()) { - final username = usernameCtrl.text; - final password = passwordCtrl.text; - accountsGrpc.signIn(username, "", password).then((rs) { - window.localStorage["token"] = rs.token; - window.localStorage["uuid"] = rs.uuid; - widget.notifyParent(); - // Navigator.of(context, rootNavigator: true).pop(); - }).catchError((e) { - GrpcError error = e; - String msg; - if (error.message != null) { - msg = error.message!; - } else { - msg = error.toString(); - } - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(msg), - backgroundColor: Colors.red, - showCloseIcon: true, - behavior: SnackBarBehavior.floating, - )); - passwordCtrl.clear(); - }); - } - } - - void subminResetPassword() { - // Validate returns true if the form is valid, or false otherwise. - if (_formKey.currentState!.validate()) { - final username = usernameCtrl.text; - final password = passwordCtrl.text; - final code = codeCtrl.text; - accountsGrpc.newPassword(username, code, password).then((rs) { - action = Action.singIn; - // Navigator.of(context, rootNavigator: true).pop(); - }).catchError((e) { - GrpcError error = e; - String msg; - if (error.message != null) { - msg = error.message!; - } else { - msg = error.toString(); - } - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(msg), - backgroundColor: Colors.red, - showCloseIcon: true, - behavior: SnackBarBehavior.floating, - )); - passwordCtrl.clear(); - }); - } - } - - void sendCode() { - if (_formKey.currentState!.validate()) { - final username = usernameCtrl.text; - final email = emailCtrl.text; - accountsGrpc - .resetPassword(username, email) - .then((_) => setState(() { - codeEnabled = true; - })) - .catchError((e) { - GrpcError error = e; - String msg; - if (error.message != null) { - msg = error.message!; - } else { - msg = error.toString(); - } - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text(msg), - backgroundColor: Colors.red, - showCloseIcon: true, - behavior: SnackBarBehavior.floating, - )); - }); - } - } - - Widget signInForm() => SizedBox( - width: 420, - height: 280, - child: Form( - key: _formKey, - child: Center( - child: Column(children: [ - TextFormField( - onFieldSubmitted: (value) => submitSignIn(), - autofocus: true, - controller: usernameCtrl, - decoration: const InputDecoration( - hintText: "Enter your username", - icon: Icon(Icons.account_circle), - label: Text("Username"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextFormField( - onFieldSubmitted: (value) => submitSignIn(), - controller: passwordCtrl, - obscureText: true, - decoration: const InputDecoration( - hintText: "Enter your password", - icon: Icon(Icons.password), - label: Text("Password")), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextButton( - onPressed: () => setState(() { - action = Action.resetPassword; - }), - child: const Text("reset yomakeur password")), - ])))); - - List signInActions() => [ - TextButton( - onPressed: () => setState(() { - action = Action.signUp; - }), - child: const Text('Sing Up'), - ), - TextButton( - onPressed: submitSignIn, - child: const Text('OK'), - ), - ]; - - List signUpActions() => [ - TextButton( - onPressed: () => setState(() { - action = Action.singIn; - }), - child: const Text('Sign In'), - ), - TextButton( - onPressed: submitSignUp, - child: const Text('OK'), - ), - ]; - - List resetPasswordActions() => [ - TextButton( - onPressed: () => setState(() { - action = Action.singIn; - }), - child: const Text('Sign In'), - ), - TextButton( - onPressed: () => setState(() { - action = Action.signUp; - }), - child: const Text('Sing Up'), - ), - TextButton( - onPressed: subminResetPassword, - child: const Text('OK'), - ), - ]; - - Widget signUpForm() => SizedBox( - width: 420, - height: 280, - child: Form( - key: _formKey, - child: Center( - child: Column(children: [ - TextFormField( - onFieldSubmitted: (value) => submitSignUp(), - autofocus: true, - controller: usernameCtrl, - decoration: const InputDecoration( - hintText: "Enter your username", - icon: Icon(Icons.account_circle), - label: Text("Username"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextFormField( - onFieldSubmitted: (value) => submitSignUp(), - controller: emailCtrl, - autofocus: true, - decoration: const InputDecoration( - hintText: "Enter your email", - icon: Icon(Icons.email), - label: Text("Email"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextFormField( - onFieldSubmitted: (value) => submitSignUp(), - controller: passwordCtrl, - obscureText: true, - decoration: const InputDecoration( - hintText: "Enter your password", - icon: Icon(Icons.password), - label: Text("Password")), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextFormField( - onFieldSubmitted: (value) => submitSignUp(), - controller: passwordVerifyCtrl, - obscureText: true, - decoration: const InputDecoration( - hintText: "Verify your password", - icon: Icon(Icons.password), - label: Text("Confirm Password")), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - ])))); - Widget resetPasswordForm() => SizedBox( - width: 420, - height: 420, - child: Form( - key: _formKey, - child: Center( - child: Column(children: [ - TextFormField( - // onFieldSubmitted: (value) => submitSignUp(), - autofocus: true, - controller: usernameCtrl, - decoration: const InputDecoration( - hintText: "Enter your username", - icon: Icon(Icons.account_circle), - label: Text("Username"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextFormField( - // onFieldSubmitted: (value) => submitSignUp(), - controller: emailCtrl, - autofocus: true, - decoration: const InputDecoration( - hintText: "Enter your email", - icon: Icon(Icons.email), - label: Text("Email"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextButton( - onPressed: () => sendCode(), child: const Text("send code to email")), - TextFormField( - // onFieldSubmitted: (value) => submitSignUp(), - controller: codeCtrl, - autofocus: false, - enabled: codeEnabled, - decoration: const InputDecoration( - hintText: "Enter code that you've received via the email", - icon: Icon(Icons.numbers), - label: Text("Code"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextFormField( - // onFieldSubmitted: (value) => submitSignUp(), - controller: passwordCtrl, - autofocus: false, - enabled: codeEnabled, - obscureText: true, - decoration: const InputDecoration( - hintText: "Enter a new password", - icon: Icon(Icons.password), - label: Text("Password"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - TextFormField( - // onFieldSubmitted: (value) => submitSignUp(), - controller: passwordVerifyCtrl, - autofocus: false, - enabled: codeEnabled, - obscureText: true, - decoration: const InputDecoration( - hintText: "Enter a new password", - icon: Icon(Icons.password), - label: Text("Password"), - ), - cursorWidth: 1, - cursorHeight: 18, - cursorRadius: const Radius.circular(10), - ), - ])))); - - @override - void initState() { - super.initState(); - accountsGrpc = AccountsGrpc(channel: widget.grpcChannel); - accountsGrpc.init(); - } - - @override - Widget build(BuildContext context) => AlertDialog( - title: const Text(dialogName), - // content: action == Action.singIn ? signInForm() : signUpForm(), - content: () { - switch (action) { - case Action.signUp: - return signUpForm(); - case Action.resetPassword: - return resetPasswordForm(); - default: - return signInForm(); - } - }(), - actions: () { - switch (action) { - case Action.signUp: - return signUpActions(); - case Action.resetPassword: - return resetPasswordActions(); - default: - return signInActions(); - } - }()); -} diff --git a/lib/components/menubar.dart b/lib/components/menubar.dart index cfc3bcd..6b6477d 100644 --- a/lib/components/menubar.dart +++ b/lib/components/menubar.dart @@ -52,16 +52,20 @@ class _MenuPanel extends State { showDialog( context: context, builder: (BuildContext context) => SignUpForm( - accountsGrpc: widget.accountsGrpc, - )); + accountsGrpc: widget.accountsGrpc, + )); }, child: const Text("sign up")), ]; } } + final String linkCatalog = "catalog"; + final String linkAbout = "about"; + final String linkHome = "home"; @override PreferredSizeWidget build(BuildContext context) { + final TabName tab = widget.tab; return AppBar( title: Row(children: [ TextButton( @@ -69,6 +73,36 @@ class _MenuPanel extends State { onPressed: () { Navigator.pushNamed(context, "/"); }), + TextButton( + child: Text( + linkHome, + style: (tab == TabName.home) + ? const TextStyle(decoration: TextDecoration.underline) + : const TextStyle(), + ), + onPressed: () { + Navigator.pushNamed(context, "/"); + }), + TextButton( + child: Text( + linkCatalog, + style: (tab == TabName.catalog) + ? const TextStyle(decoration: TextDecoration.underline) + : const TextStyle(), + ), + onPressed: () { + Navigator.pushNamed(context, "/catalog"); + }), + TextButton( + child: Text( + linkAbout, + style: (tab == TabName.about) + ? const TextStyle(decoration: TextDecoration.underline) + : const TextStyle(), + ), + onPressed: () { + Navigator.pushNamed(context, "/about"); + }), ]), backgroundColor: const Color.fromRGBO(46, 51, 78, 1.0), automaticallyImplyLeading: false, diff --git a/lib/components/sign_in_form.dart b/lib/components/sign_in_form.dart new file mode 100644 index 0000000..ddc7dd3 --- /dev/null +++ b/lib/components/sign_in_form.dart @@ -0,0 +1,106 @@ +import 'dart:html'; + +import 'package:flutter/material.dart'; +import 'package:grpc/grpc_web.dart'; +import 'package:softplayer_web/api/grpc/accounts.dart'; + +class SignInForm extends StatefulWidget { + const SignInForm({ + super.key, + required this.accountsGrpc, + }); + + final AccountsGrpc accountsGrpc; + @override + State createState() => _SignInFormState(); +} + +class _SignInFormState extends State { + final _formKey = GlobalKey(); + final usernameCtrl = TextEditingController(); + final passwordCtrl = TextEditingController(); + static const dialogName = "Sign In"; + void submitForm() { + // Validate returns true if the form is valid, or false otherwise. + if (_formKey.currentState!.validate()) { + final username = usernameCtrl.text; + final password = passwordCtrl.text; + widget.accountsGrpc + .signIn(username, "", password) + .then((rs) { + window.localStorage["token"] = rs.token; + window.localStorage["uuid"] = rs.uuid; + Navigator.of(context, rootNavigator: true).pop(); + }) + .catchError((e) { + GrpcError error = e; + String msg; + if (error.message != null) { + msg = error.message!; + } else { + msg = error.toString(); + } + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(msg), + backgroundColor: Colors.red, + showCloseIcon: true, + behavior: SnackBarBehavior.floating, + )); + passwordCtrl.clear(); + }); + } + } + + @override + Widget build(BuildContext context) => AlertDialog( + title: const Text(dialogName), + content: SizedBox( + width: 420, + height: 140, + child: Form( + key: _formKey, + child: Center( + child: Column(children: [ + TextFormField( + controller: usernameCtrl, + autofocus: true, + decoration: const InputDecoration( + hintText: "Enter your username or email", + icon: Icon(Icons.account_circle), + label: Text("Username"), + ), + cursorWidth: 1, + cursorHeight: 18, + cursorRadius: const Radius.circular(10), + ), + TextFormField( + controller: passwordCtrl, + obscureText: true, + decoration: const InputDecoration( + hintText: "Enter your password", + icon: Icon(Icons.password), + label: Text("Password")), + cursorWidth: 1, + cursorHeight: 18, + cursorRadius: const Radius.circular(10), + onFieldSubmitted: (v) { + if (usernameCtrl.text.isEmpty) { + FocusScope.of(context).nextFocus(); + } else { + submitForm(); + } + }, + ), + ])))), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context, 'Cancel'), + child: const Text('Cancel'), + ), + TextButton( + onPressed: submitForm, + child: const Text('OK'), + ), + ], + ); +} diff --git a/lib/components/sign_up_form.dart b/lib/components/sign_up_form.dart new file mode 100644 index 0000000..e3023ec --- /dev/null +++ b/lib/components/sign_up_form.dart @@ -0,0 +1,129 @@ +import 'dart:html'; + +import 'package:flutter/material.dart'; +import 'package:grpc/grpc_web.dart'; +import 'package:softplayer_web/api/grpc/accounts.dart'; + +class SignUpForm extends StatefulWidget { + const SignUpForm({ + super.key, + required this.accountsGrpc, + + }); + + final AccountsGrpc accountsGrpc; + @override + State createState() => _SignUpFormState(); +} + +class _SignUpFormState extends State { + final _formKey = GlobalKey(); + + final usernameCtrl = TextEditingController(); + final passwordCtrl = TextEditingController(); + final passwordVerifyCtrl = TextEditingController(); + final emailCtrl = TextEditingController(); + + static const dialogName = "Sign Up"; + + void submitForm() { + // Validate returns true if the form is valid, or false otherwise. + if (_formKey.currentState!.validate()) { + final username = usernameCtrl.text; + final password = passwordCtrl.text; + final email = emailCtrl.text; + widget.accountsGrpc + .signUp(username, email, password) + .then((rs) { + window.localStorage["token"] = rs.token; + window.localStorage["uuid"] = rs.uuid; + Navigator.of(context, rootNavigator: true).pop(); + }) + + .catchError((e) { + GrpcError error = e; + String msg; + if (error.message != null) { + msg = error.message!; + } else { + msg = error.toString(); + } + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(msg), + backgroundColor: Colors.red, + showCloseIcon: true, + behavior: SnackBarBehavior.floating, + )); + passwordCtrl.clear(); + }); + } + } + @override + Widget build(BuildContext context) => AlertDialog( + title: const Text(dialogName), + content: SizedBox( + width: 420, + height: 280, + child: Form( + key: _formKey, + child: Center( + child: Column(children: [ + TextFormField( + autofocus: true, + controller: usernameCtrl, + decoration: const InputDecoration( + hintText: "Enter your username", + icon: Icon(Icons.account_circle), + label: Text("Username"), + ), + cursorWidth: 1, + cursorHeight: 18, + cursorRadius: const Radius.circular(10), + ), + TextFormField( + controller: emailCtrl, + autofocus: true, + decoration: const InputDecoration( + hintText: "Enter your email", + icon: Icon(Icons.email), + label: Text("Email"), + ), + cursorWidth: 1, + cursorHeight: 18, + cursorRadius: const Radius.circular(10), + ), + TextFormField( + controller: passwordCtrl, + obscureText: true, + decoration: const InputDecoration( + hintText: "Enter your password", + icon: Icon(Icons.password), + label: Text("Password")), + cursorWidth: 1, + cursorHeight: 18, + cursorRadius: const Radius.circular(10), + ), + TextFormField( + controller: passwordVerifyCtrl, + obscureText: true, + decoration: const InputDecoration( + hintText: "Verify your password", + icon: Icon(Icons.password), + label: Text("Confirm Password")), + cursorWidth: 1, + cursorHeight: 18, + cursorRadius: const Radius.circular(10), + ), + ])))), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context, 'Cancel'), + child: const Text('Cancel'), + ), + TextButton( + onPressed: submitForm, + child: const Text('OK'), + ), + ], + ); +} diff --git a/lib/helpers/page_wrapper.dart b/lib/helpers/page_wrapper.dart index 03e0a02..f101848 100644 --- a/lib/helpers/page_wrapper.dart +++ b/lib/helpers/page_wrapper.dart @@ -1,22 +1,10 @@ -import 'dart:html'; - import 'package:flutter/material.dart'; -import 'package:softplayer_web/api/grpc/accounts.dart'; import 'package:softplayer_web/components/menubar.dart'; class PageWrapper extends StatelessWidget { final Widget child; final MenuPanel appBar; - const PageWrapper( - {super.key, - required this.child, - required this.appBar, - required this.accountsGrpc}); - - final AccountsGrpc accountsGrpc; - bool isSignedIn() { - return window.localStorage.containsKey("token"); - } + const PageWrapper({super.key, required this.child, required this.appBar}); @override Widget build(BuildContext context) { diff --git a/lib/helpers/providers/common.dart b/lib/helpers/providers/common.dart deleted file mode 100644 index 7973c47..0000000 --- a/lib/helpers/providers/common.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'package:softplayer_dart_proto/environments/environments_v1.pbenum.dart'; -import 'package:softplayer_web/helpers/providers/hetzner.dart'; - -abstract class Provider { - String getServerLocation(String serverLocation); - String rawServerLocation(String serverLocation); - String defaultLocation(); - - String getProviderName(); - String rawProviderName(); -} - -class ProviderHelper { - String getServerType(String serverType) { - if (serverType == ServerType.SERVER_TYPE_STARTER.toString()) { - return "Starter"; - } else if (serverType == ServerType.SERVER_TYPE_REGULAR.toString()) { - return "Regular"; - } else if (serverType == ServerType.SERVER_TYPE_PLUS.toString()) { - return "Plus"; - } else if (serverType == ServerType.SERVER_TYPE_PRO.toString()) { - return "Pro"; - } else if (serverType == ServerType.SERVER_TYPE_CUSTOM.toString()) { - throw 'Custom server type is not yet supported'; - } else { - throw 'Unknown server type'; - } - } - - String rawServerType(String serverType) { - if (serverType == "Starter") { - return ServerType.SERVER_TYPE_STARTER.toString(); - } else if (serverType == "Regular") { - return ServerType.SERVER_TYPE_REGULAR.toString(); - } else if (serverType == "Plus") { - return ServerType.SERVER_TYPE_PLUS.toString(); - } else if (serverType == "Pro") { - return ServerType.SERVER_TYPE_PRO.toString(); - } else { - throw 'Unknown server type'; - } - } - - Hetzner getProvider(String provider) { - switch (provider) { - case "hetzner" || "PROVIDER_HETZNER": - return Hetzner(); - default: - throw "unknown prodiver"; - } - } -} diff --git a/lib/helpers/providers/hetzner.dart b/lib/helpers/providers/hetzner.dart deleted file mode 100644 index 8e8a9ca..0000000 --- a/lib/helpers/providers/hetzner.dart +++ /dev/null @@ -1,53 +0,0 @@ -import 'package:softplayer_dart_proto/environments/environments_v1.pbgrpc.dart'; -import 'package:softplayer_web/helpers/providers/common.dart' as helper; - -class Hetzner implements helper.Provider { - @override - String getProviderName() { - return "Hetzner"; - } - - @override - String rawProviderName() { - return Provider.PROVIDER_HETZNER.toString(); - } - - @override - String getServerLocation(String serverType) { - if (serverType == Location.LOCATION_HETZNER_ASHBURN.toString()) { - return "Ashburn, USA"; - } else if (serverType == Location.LOCATION_HETZNER_FALKENSTEIN.toString()) { - return "Falkenstein, Germany"; - } else if (serverType == Location.LOCATION_HETZNER_HELSINKI.toString()) { - return "Helsinki, Finland"; - } else if (serverType == Location.LOCATION_HETZNER_HILLSBORO.toString()) { - return "Hillsboro, USA"; - } else if (serverType == Location.LOCATION_HETZNER_NUREMBERG.toString()) { - return "Nuremberg, Germany"; - } else { - throw 'Unknown server type'; - } - } - - @override - String rawServerLocation(String serverLocation) { - if (serverLocation == "Ashburn, USA") { - return Location.LOCATION_HETZNER_ASHBURN.toString(); - } else if (serverLocation == "Falkenstein, Germany") { - return Location.LOCATION_HETZNER_FALKENSTEIN.toString(); - } else if (serverLocation == "Helsinki, Finland") { - return Location.LOCATION_HETZNER_HELSINKI.toString(); - } else if (serverLocation == "Hillsboro, USA") { - return Location.LOCATION_HETZNER_HILLSBORO.toString(); - } else if (serverLocation == "Nuremberg, Germany") { - return Location.LOCATION_HETZNER_NUREMBERG.toString(); - } else { - throw 'Unknown server type'; - } - } - - @override - String defaultLocation() { - return Location.LOCATION_HETZNER_NUREMBERG.toString(); - } -} diff --git a/lib/main.dart b/lib/main.dart index e2c89aa..f778def 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,17 +1,17 @@ -import 'dart:html'; - -import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter/material.dart'; import 'package:grpc/grpc_web.dart'; import 'package:softplayer_web/api/grpc/accounts.dart'; -import 'package:softplayer_web/api/grpc/creds.dart'; -import 'package:softplayer_web/components/create_env_form.dart'; -import 'package:softplayer_web/components/environments.dart'; -import 'package:softplayer_web/components/login_form.dart'; +import 'package:softplayer_web/components/menubar.dart'; +import 'package:softplayer_web/helpers/page_wrapper.dart'; +import 'package:softplayer_web/pages/about.dart'; +import 'package:softplayer_web/pages/catalog.dart'; +import 'package:softplayer_web/pages/home.dart'; void main() async { - await dotenv.load(fileName: ".env"); - String backendURL = dotenv.env['SOFTPLAYER_BACKEND_URL']!; + const String backendURL = String.fromEnvironment( + 'SOFTPLAYER_BACKEND_URL', + defaultValue: 'https://softplayer-backend.badhouseplants.net:8080', + ); GrpcWebClientChannel grpcChannel = GrpcWebClientChannel.xhr(Uri.parse(backendURL)); @@ -28,7 +28,29 @@ class MyApp extends StatelessWidget { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Softplayer', - home: RootWidget(channel: channel), + routes: { + '/': (context) => PageWrapper( + appBar: MenuPanel( + tab: TabName.home, + accountsGrpc: accountsGrpc, + ), + child: const HomePage(), + ), + '/catalog': (context) => PageWrapper( + appBar: MenuPanel( + tab: TabName.catalog, + accountsGrpc: accountsGrpc, + ), + child: const CatalogPage(), + ), + '/about': (context) => PageWrapper( + appBar: MenuPanel( + tab: TabName.about, + accountsGrpc: accountsGrpc, + ), + child: const AboutPage(), + ) + }, theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, @@ -36,112 +58,3 @@ class MyApp extends StatelessWidget { ); } } - -class RootWidget extends StatefulWidget { - final GrpcWebClientChannel channel; - - RootWidget({super.key, required this.channel}); - late final AccountsGrpc accountsGrpc = AccountsGrpc(channel: channel); - - @override - @override - State createState() => _StateRootWidget(); -} - -class _StateRootWidget extends State { - refresh() { - setState(() {}); - } - - bool isSignedIn() { - return window.localStorage.containsKey("token"); - } - - final GlobalKey _key = GlobalKey(); // Create a key - @override - Widget build(BuildContext context) { - if (!isSignedIn()) { - return Scaffold( - body: Container( - width: double.infinity, - height: double.infinity, - decoration: const BoxDecoration( - image: DecorationImage( - image: AssetImage("assets/login_background.jpg"), - fit: BoxFit.cover, - ), - ), - child: LoginForm( - grpcChannel: widget.channel, - notifyParent: refresh, - ), - )); - } else { - EnvirnomentList envList = EnvirnomentList(channel: widget.channel); - return DefaultTabController( - length: 3, - initialIndex: 0, - child: Scaffold( - key: _key, - endDrawer: const Drawer(child: Text("text")), - body: TabBarView(children: [envList, envList]), - appBar: AppBar( - backgroundColor: Colors.grey, - centerTitle: false, - title: const Text("Softplayer"), - bottom: const TabBar( - tabs: [ - Tab( - icon: Icon(Icons.computer), - text: "Environments", - ), - Tab( - icon: Icon(Icons.install_desktop), - text: "Your applications", - ), - Tab( - icon: Icon(Icons.list), - text: "Application Catalog", - ), - ], - ), - actions: [ - PopupMenuButton( - child: const Row(children: [ - Icon(Icons.account_circle), - Text("account"), - ]), - itemBuilder: (context) => [ - const PopupMenuItem( - child: Row( - children: [Icon(Icons.settings), Text("Settings")], - ), - ), - const PopupMenuItem( - child: Row(children: [ - Icon(Icons.monetization_on), - Text("Invoices"), - ])), - PopupMenuItem( - child: const Row( - children: [Icon(Icons.logout), Text("Sign out")]), - onTap: () { - SoftplayerCredsHelpers().cleanupLocalStorate(); - refresh(); - }, - ), - ]) - ], - ), - floatingActionButton: FloatingActionButton( - child: const Icon(Icons.add), - onPressed: () => showDialog( - context: context, - builder: (context) => CreateEnvForm(widget.channel), - ), - ), - ), - ); - } - } -} diff --git a/lib/models/environments.dart b/lib/models/environments.dart deleted file mode 100644 index c90f35c..0000000 --- a/lib/models/environments.dart +++ /dev/null @@ -1,10 +0,0 @@ -class Environment { - final String name; - final List apps; - final String provider; - Environment({ - required this.name, - required this.apps, - required this.provider, - }); -} diff --git a/pubspec.lock b/pubspec.lock index 096e92c..5cc5cbf 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,18 +5,18 @@ packages: dependency: transitive description: name: archive - sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265 + sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" url: "https://pub.dev" source: hosted - version: "3.5.1" + version: "3.4.10" args: dependency: transitive description: name: args - sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 url: "https://pub.dev" source: hosted - version: "2.5.0" + version: "2.4.2" async: dependency: transitive description: @@ -57,6 +57,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" crypto: dependency: transitive description: @@ -69,18 +77,18 @@ packages: dependency: "direct main" description: name: cupertino_icons - sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d url: "https://pub.dev" source: hosted - version: "1.0.8" + version: "1.0.6" dio: dependency: "direct main" description: name: dio - sha256: "11e40df547d418cc0c4900a9318b26304e665da6fa4755399a9ff9efd09034b5" + sha256: "0978e9a3e45305a80a7210dbeaf79d6ee8bee33f70c8e542dc654c952070217f" url: "https://pub.dev" source: hosted - version: "5.4.3+1" + version: "5.4.2+1" fake_async: dependency: transitive description: @@ -102,14 +110,6 @@ packages: description: flutter source: sdk version: "0.0.0" - flutter_dotenv: - dependency: "direct main" - description: - name: flutter_dotenv - sha256: "9357883bdd153ab78cbf9ffa07656e336b8bbb2b5a3ca596b0b27e119f7c7d77" - url: "https://pub.dev" - source: hosted - version: "5.1.0" flutter_lints: dependency: "direct dev" description: @@ -135,10 +135,10 @@ packages: dependency: transitive description: name: googleapis_auth - sha256: befd71383a955535060acde8792e7efc11d2fccd03dd1d3ec434e85b68775938 + sha256: "1401a9e55f9e0f565d3eebb18d990290f53a12d38a5f7f0230b112895778a85b" url: "https://pub.dev" source: hosted - version: "1.6.0" + version: "1.5.1" grpc: dependency: "direct main" description: @@ -171,6 +171,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + js: + dependency: transitive + description: + name: js + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf + url: "https://pub.dev" + source: hosted + version: "0.7.1" leak_tracker: dependency: transitive description: @@ -235,6 +243,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" + url: "https://pub.dev" + source: hosted + version: "3.7.4" protobuf: dependency: transitive description: @@ -253,7 +269,7 @@ packages: description: path: "." ref: main - resolved-ref: "5ee911c92eee4ee7db58a2da0407da4f7db2f994" + resolved-ref: eb11f022be9c1fc5db6e87f3463a1ceb3e04501f url: "https://git.badhouseplants.net/softplayer/softplayer-dart-proto.git" source: git version: "1.0.0+1" diff --git a/pubspec.yaml b/pubspec.yaml index 52ee53e..3d57b0c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -18,7 +18,6 @@ dependencies: grpc: ^3.2.4 http: ^1.2.1 dio: ^5.4.2 - flutter_dotenv: ^5.1.0 dev_dependencies: flutter_test: @@ -27,6 +26,3 @@ dev_dependencies: flutter: uses-material-design: true - assets: - - assets/ - - .env \ No newline at end of file