diff --git a/android/app/src/main/kotlin/net/defined/mobile_nebula/MainActivity.kt b/android/app/src/main/kotlin/net/defined/mobile_nebula/MainActivity.kt index a5d35ce..3597041 100644 --- a/android/app/src/main/kotlin/net/defined/mobile_nebula/MainActivity.kt +++ b/android/app/src/main/kotlin/net/defined/mobile_nebula/MainActivity.kt @@ -356,7 +356,8 @@ class MainActivity: FlutterActivity() { return result.success(null) } - return result.error("denied", "User did not grant permission", null) + //NOTE: flutter side doesn't care about the message currently, only the code + return result.error("PERMISSIONS", "User did not grant permission", null) } else if (requestCode == VPN_START_CODE) { // We are processing a response for permissions while starting the VPN (or reusing code in the event we already have perms) diff --git a/lib/screens/MainScreen.dart b/lib/screens/MainScreen.dart index 3d1df58..a93ad01 100644 --- a/lib/screens/MainScreen.dart +++ b/lib/screens/MainScreen.dart @@ -32,6 +32,8 @@ class MainScreen extends StatefulWidget { class _MainScreenState extends State { bool ready = false; List sites; + // A set of widgets to display in a column that represents an error blocking us from moving forward entirely + List error; static const platform = MethodChannel('net.defined.mobileNebula/NebulaVpnService'); @@ -69,6 +71,14 @@ class _MainScreenState extends State { } Widget _buildBody() { + if (error != null) { + return Center(child: Padding(child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: error, + ), padding: EdgeInsets.symmetric(vertical: 0, horizontal: 10))); + } + if (!ready) { return Center( child: PlatformCircularProgressIndicator(cupertino: (_, __) { @@ -197,7 +207,44 @@ rmXnR1yvDZi1VPVmnNVY8NMsQpEpbbYlq7rul+ByQvg= _loadSites() async { if (Platform.isAndroid) { - await platform.invokeMethod("android.requestPermissions"); + try { + await platform.invokeMethod("android.requestPermissions"); + + } on PlatformException catch (err) { + if (err.code == "PERMISSIONS") { + setState(() { + error = [ + Text("Permissions Required", + style: TextStyle(fontWeight: FontWeight.bold)), + Text( + "VPN permissions are required for nebula to run, click the button below request and accept the appropriate permissions.", + textAlign: TextAlign.center + ), + ElevatedButton( + onPressed: () { + error = null; + _loadSites(); + }, + child: Text("Request Permissions") + ), + ]; + }); + } else { + setState(() { + error = [ + Text("Unknown Error", style: TextStyle(fontWeight: FontWeight.bold)), + Text(err.message, textAlign: TextAlign.center) + ]; + }); + } + } catch (err) { + setState(() { + error = [ + Text("Unknown Error", style: TextStyle(fontWeight: FontWeight.bold)), + Text(err.message, textAlign: TextAlign.center) + ]; + }); + } } //TODO: This can throw, we need to show an error dialog