add settings page so set ssh login

request storage permissions on android
This commit is contained in:
lukas-heiligenbrunner 2022-09-28 15:31:24 +02:00
parent 2ba9fb3fbd
commit 369da56258
12 changed files with 233 additions and 24 deletions

View File

@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion flutter.compileSdkVersion
compileSdkVersion 33
ndkVersion flutter.ndkVersion
compileOptions {

View File

@ -1,5 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="eu.heili.gallery">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<application
android:label="gallery"
android:name="${applicationName}"

View File

@ -6,6 +6,11 @@ class Item {
String name;
Item(this.isFolder, this.uri, this.name);
@override
String toString() {
return 'Item{isFolder: $isFolder, uri: $uri, name: $name}';
}
}
class Folder {

View File

@ -10,11 +10,11 @@ import 'dart:ui' as ui show Codec, ImmutableBuffer;
import 'package:path_provider/path_provider.dart';
class SSHDataProvider extends DataProvider {
final String host;
final int port;
final String username;
final String password;
final String initialPath;
final Future<String> host;
final Future<int> port;
final Future<String> username;
final Future<String> password;
final Future<String> initialPath;
SftpClient? sftpClient;
SSHClient? sshClient;
@ -31,8 +31,8 @@ class SSHDataProvider extends DataProvider {
if (sshClient != null && !sshClient!.isClosed) return;
sshClient = SSHClient(
await SSHSocket.connect(host, port),
username: username,
await SSHSocket.connect(await host, await port),
username: await username,
onPasswordRequest: () => password,
);
await sshClient?.authenticated;
@ -45,7 +45,8 @@ class SSHDataProvider extends DataProvider {
await connect();
if (sftpClient == null) throw const FormatException("");
final dir = uri != null ? Directory.fromUri(uri) : Directory(initialPath);
final dir =
uri != null ? Directory.fromUri(uri) : Directory(await initialPath);
final items = await sftpClient!.listdir(dir.path);
List<Item> res = [];

View File

@ -1,8 +1,9 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:gallery/data_provider/data_provider.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:gallery/image_grid.dart';
import 'package:gallery/settings_page.dart';
import 'package:path_provider/path_provider.dart';
import 'data_provider/local_data_provider.dart';
@ -17,7 +18,7 @@ class MyHomePage extends StatefulWidget {
State<MyHomePage> createState() => _MyHomePageState();
}
enum Page { local, remote }
enum Page { local, remote, settings }
class _MyHomePageState extends State<MyHomePage> {
Page page = Page.local;
@ -34,19 +35,27 @@ class _MyHomePageState extends State<MyHomePage> {
}
Widget _buildPage() {
DataProvider provider;
switch (page) {
case Page.local:
provider = LocalDataProvider(_getLocalDir());
break;
return ImageGrid(dProvider: LocalDataProvider(_getLocalDir()));
case Page.remote:
// todo do not generate a new provider on each tab switch
provider = SSHDataProvider(
initialPath: "/", host: "", password: "", port: 0, username: "");
break;
const storage = FlutterSecureStorage();
return ImageGrid(
dProvider: SSHDataProvider(
initialPath:
Future.value("/media/3TBRaid/3TBRaid/Bilder/2022/"),
host: (() async => (await storage.read(key: "host")) ?? "")
.call(),
password:
(() async => (await storage.read(key: "pwd")) ?? "").call(),
port: Future.value(22),
username: (() async => (await storage.read(key: "user")) ?? "")
.call()));
case Page.settings:
return const SettingsPage();
}
return ImageGrid(dProvider: provider);
}
@override
@ -84,6 +93,15 @@ class _MyHomePageState extends State<MyHomePage> {
Navigator.pop(context);
},
),
ListTile(
title: const Text('Settings'),
onTap: () {
setState(() {
page = Page.settings;
});
Navigator.pop(context);
},
),
],
),
),

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'data_provider/data_provider.dart';
@ -41,13 +43,15 @@ class _ImageGridState extends State<ImageGrid> {
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisSpacing: 0,
mainAxisSpacing: 0,
crossAxisCount: width ~/ 300,
crossAxisCount:
Platform.isAndroid ? width ~/ 100 : width ~/ 300,
),
itemCount: data.items.length + 1,
itemBuilder: (context, index) {
if (index == 0) {
return ImageTile(
child: const Icon(Icons.arrow_back, size: 142),
child: Icon(Icons.arrow_back,
size: Platform.isAndroid ? 64 : 142),
onClick: () {
setState(() {
folder = widget.dProvider.listOfFiles(uri: data.parent);
@ -93,7 +97,8 @@ class _ImageGridState extends State<ImageGrid> {
? Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.folder_open, size: 142),
Icon(Icons.folder_open,
size: Platform.isAndroid ? 64 : 142),
Text(elem.name)
],
)

View File

@ -1,11 +1,21 @@
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'home_page.dart';
void main() {
runApp(const MyApp());
void main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) {
if (await Permission.storage.request().isGranted) {
runApp(const MyApp());
}
} else {
runApp(const MyApp());
}
}
class AppScrollBehavior extends MaterialScrollBehavior {

79
lib/settings_page.dart Normal file
View File

@ -0,0 +1,79 @@
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class SettingsPage extends StatefulWidget {
const SettingsPage({Key? key}) : super(key: key);
@override
State<SettingsPage> createState() => _SettingsPageState();
}
class _SettingsPageState extends State<SettingsPage> {
late TextEditingController _controllerHost;
late TextEditingController _controllerUser;
late TextEditingController _controllerPwd;
@override
void initState() {
super.initState();
_controllerHost = TextEditingController();
_controllerUser = TextEditingController();
_controllerPwd = TextEditingController();
const storage = FlutterSecureStorage();
storage
.read(key: "host")
.then((value) => _controllerHost.text = value ?? "");
storage
.read(key: "user")
.then((value) => _controllerUser.text = value ?? "");
storage.read(key: "pwd").then((value) => _controllerPwd.text = value ?? "");
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(5),
child: Column(
children: [
const SizedBox(
height: 10,
),
TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(), labelText: "host"),
controller: _controllerHost,
),
const SizedBox(
height: 5,
),
TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(), labelText: "user"),
controller: _controllerUser,
),
const SizedBox(
height: 5,
),
TextField(
obscureText: true,
decoration: const InputDecoration(
border: OutlineInputBorder(), labelText: "password"),
controller: _controllerPwd,
),
const SizedBox(
height: 5,
),
TextButton(
onPressed: () {
const storage = FlutterSecureStorage();
storage.write(key: "host", value: _controllerHost.value.text);
storage.write(key: "user", value: _controllerUser.value.text);
storage.write(key: "pwd", value: _controllerPwd.value.text);
},
child: const Text("Save"))
],
),
);
}
}

View File

@ -6,6 +6,10 @@
#include "generated_plugin_registrant.h"
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar =
fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin");
flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar);
}

View File

@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
flutter_secure_storage_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST

View File

@ -111,11 +111,58 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
flutter_secure_storage:
dependency: "direct main"
description:
name: flutter_secure_storage
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.0"
flutter_secure_storage_linux:
dependency: transitive
description:
name: flutter_secure_storage_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
flutter_secure_storage_macos:
dependency: transitive
description:
name: flutter_secure_storage_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.1"
flutter_secure_storage_platform_interface:
dependency: transitive
description:
name: flutter_secure_storage_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_secure_storage_web:
dependency: transitive
description:
name: flutter_secure_storage_web
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.2"
flutter_secure_storage_windows:
dependency: transitive
description:
name: flutter_secure_storage_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
intl:
dependency: transitive
description:
@ -214,6 +261,41 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
permission_handler:
dependency: "direct main"
description:
name: permission_handler
url: "https://pub.dartlang.org"
source: hosted
version: "10.0.2"
permission_handler_android:
dependency: transitive
description:
name: permission_handler_android
url: "https://pub.dartlang.org"
source: hosted
version: "10.0.0"
permission_handler_apple:
dependency: transitive
description:
name: permission_handler_apple
url: "https://pub.dartlang.org"
source: hosted
version: "9.0.4"
permission_handler_platform_interface:
dependency: transitive
description:
name: permission_handler_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "3.8.0"
permission_handler_windows:
dependency: transitive
description:
name: permission_handler_windows
url: "https://pub.dartlang.org"
source: hosted
version: "0.1.0"
pinenacl:
dependency: transitive
description:

View File

@ -38,6 +38,8 @@ dependencies:
cupertino_icons: ^1.0.2
path_provider: ^2.0.11
dartssh2: ^2.7.2+3
permission_handler: ^10.0.2
flutter_secure_storage: ^6.0.0
dev_dependencies:
flutter_test: