add settings page so set ssh login
request storage permissions on android
This commit is contained in:
parent
2ba9fb3fbd
commit
369da56258
@ -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 {
|
||||
|
@ -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}"
|
||||
|
@ -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 {
|
||||
|
@ -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 = [];
|
||||
|
@ -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);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -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)
|
||||
],
|
||||
)
|
||||
|
@ -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() {
|
||||
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
79
lib/settings_page.dart
Normal 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"))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
flutter_secure_storage_linux
|
||||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
|
82
pubspec.lock
82
pubspec.lock
@ -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:
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user