mirror of
https://github.com/simon-ding/polaris.git
synced 2026-06-09 03:27:39 +08:00
feat: change storage setting
This commit is contained in:
@@ -115,7 +115,23 @@ class MyApp extends StatelessWidget {
|
||||
return ProviderScope(
|
||||
child: MaterialApp.router(
|
||||
title: 'Polaris',
|
||||
|
||||
theme: ThemeData(
|
||||
|
||||
// Define the default TextTheme. Use this to specify the default
|
||||
// text styling for headlines, titles, bodies of text, and more.
|
||||
// textTheme: const TextTheme(
|
||||
// bodyLarge: TextStyle(fontFamilyFallback: ["PingFang SC", "Heiti SC"]),
|
||||
// bodyMedium: TextStyle(fontFamilyFallback: ["PingFang SC", "Heiti SC"]),
|
||||
// bodySmall: TextStyle(fontFamilyFallback: ["PingFang SC", "Heiti SC"]),
|
||||
// titleLarge: TextStyle(fontFamilyFallback: ["PingFang SC", "Heiti SC"]),
|
||||
// titleMedium: TextStyle(fontFamilyFallback: ["PingFang SC", "Heiti SC"]),
|
||||
// titleSmall: TextStyle(fontFamilyFallback: ["PingFang SC", "Heiti SC"]),
|
||||
// labelLarge: TextStyle(fontFamilyFallback: ["PingFang SC", "Heiti SC"]),
|
||||
// labelMedium: TextStyle(fontFamilyFallback: ["PingFang SC", "Heiti SC"]),
|
||||
// labelSmall: TextStyle(fontFamilyFallback: ["PingFang SC", "Heiti SC"]),
|
||||
// ),
|
||||
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: Colors.blue, brightness: Brightness.dark),
|
||||
useMaterial3: true,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:quiver/strings.dart';
|
||||
@@ -246,30 +247,21 @@ class StorageSettingData extends AsyncNotifier<List<Storage>> {
|
||||
}
|
||||
|
||||
class Storage {
|
||||
Storage({
|
||||
this.id,
|
||||
this.name,
|
||||
this.implementation,
|
||||
this.path,
|
||||
this.user,
|
||||
this.password,
|
||||
});
|
||||
Storage({this.id, this.name, this.implementation, this.settings, this.isDefault});
|
||||
|
||||
final int? id;
|
||||
final String? name;
|
||||
final String? implementation;
|
||||
final String? path;
|
||||
final String? user;
|
||||
final String? password;
|
||||
final Map<String, dynamic>? settings;
|
||||
final bool? isDefault;
|
||||
|
||||
factory Storage.fromJson(Map<String, dynamic> json) {
|
||||
factory Storage.fromJson(Map<String, dynamic> json1) {
|
||||
return Storage(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
implementation: json["implementation"],
|
||||
path: json["path"],
|
||||
user: json["user"],
|
||||
password: json["password"],
|
||||
id: json1["id"],
|
||||
name: json1["name"],
|
||||
implementation: json1["implementation"],
|
||||
settings: json.decode(json1["settings"]),
|
||||
isDefault: json1["default"]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -277,8 +269,7 @@ class Storage {
|
||||
"id": id,
|
||||
"name": name,
|
||||
"implementation": implementation,
|
||||
"path": path,
|
||||
"user": user,
|
||||
"password": password,
|
||||
"settings": settings,
|
||||
"default": isDefault,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -106,73 +106,80 @@ class _SearchPageState extends ConsumerState<SearchPage> {
|
||||
}
|
||||
|
||||
Future<void> _showSubmitDialog(BuildContext context, SearchResult item) {
|
||||
String _resSelected = "1080p";
|
||||
int _storageSelected = 0;
|
||||
var storage = ref.watch(storageSettingProvider);
|
||||
return showDialog<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('添加剧集: ${item.name}'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
DropdownMenu(
|
||||
label: const Text("清晰度"),
|
||||
initialSelection: _resSelected,
|
||||
dropdownMenuEntries: const [
|
||||
DropdownMenuEntry(value: "720p", label: "720p"),
|
||||
DropdownMenuEntry(value: "1080p", label: "1080p"),
|
||||
DropdownMenuEntry(value: "4k", label: "4k"),
|
||||
],
|
||||
onSelected: (value) {
|
||||
setState(() {
|
||||
_resSelected = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
storage.when(
|
||||
data: (v) {
|
||||
return DropdownMenu(
|
||||
label: const Text("存储位置"),
|
||||
initialSelection: _storageSelected,
|
||||
dropdownMenuEntries: v
|
||||
.map((s) =>
|
||||
DropdownMenuEntry(label: s.name!, value: s.id))
|
||||
.toList(),
|
||||
onSelected: (value) {
|
||||
setState(() {
|
||||
_storageSelected = value!;
|
||||
});
|
||||
return StatefulBuilder(
|
||||
builder: (context, setState) {
|
||||
String _resSelected = "1080p";
|
||||
Storage? _storageSelected;
|
||||
var storage = ref.watch(storageSettingProvider);
|
||||
|
||||
return AlertDialog(
|
||||
title: Text('添加剧集: ${item.name}'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
DropdownMenu(
|
||||
label: const Text("清晰度"),
|
||||
initialSelection: _resSelected,
|
||||
dropdownMenuEntries: const [
|
||||
DropdownMenuEntry(value: "720p", label: "720p"),
|
||||
DropdownMenuEntry(value: "1080p", label: "1080p"),
|
||||
DropdownMenuEntry(value: "4k", label: "4k"),
|
||||
],
|
||||
onSelected: (value) {
|
||||
setState(() {
|
||||
_resSelected = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
storage.when(
|
||||
data: (v) {
|
||||
return DropdownMenu(
|
||||
label: const Text("存储位置"),
|
||||
initialSelection: _storageSelected,
|
||||
dropdownMenuEntries: v
|
||||
.map((s) =>
|
||||
DropdownMenuEntry(label: s.name!, value: s))
|
||||
.toList(),
|
||||
onSelected: (value) {
|
||||
setState(() {
|
||||
_storageSelected = value;
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
error: (err, trace) => Text("$err"),
|
||||
loading: () => const MyProgressIndicator()),
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: Theme.of(context).textTheme.labelLarge,
|
||||
),
|
||||
child: const Text('取消'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
error: (err, trace) => Text("$err"),
|
||||
loading: () => MyProgressIndicator()),
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: Theme.of(context).textTheme.labelLarge,
|
||||
),
|
||||
child: const Text('取消'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: Theme.of(context).textTheme.labelLarge,
|
||||
),
|
||||
child: const Text('确定'),
|
||||
onPressed: () {
|
||||
ref.read(searchPageDataProvider.notifier).submit2Watchlist(
|
||||
item.id!, _storageSelected, _resSelected);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(
|
||||
textStyle: Theme.of(context).textTheme.labelLarge,
|
||||
),
|
||||
child: const Text('确定'),
|
||||
onPressed: () {
|
||||
ref
|
||||
.read(searchPageDataProvider.notifier)
|
||||
.submit2Watchlist(
|
||||
item.id!, _storageSelected!.id!, _resSelected);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -473,84 +473,121 @@ class _SystemSettingsPageState extends ConsumerState<SystemSettingsPage> {
|
||||
|
||||
Future<void> showStorageDetails(
|
||||
AsyncSnapshot<void> snapshot, BuildContext context, Storage s) {
|
||||
var nameController = TextEditingController(text: s.name);
|
||||
var implController = TextEditingController(
|
||||
text: isBlank(s.implementation) ? "transmission" : s.implementation);
|
||||
var pathController = TextEditingController(text: s.path);
|
||||
var userController = TextEditingController(text: s.user);
|
||||
var passController = TextEditingController(text: s.password);
|
||||
|
||||
return showDialog<void>(
|
||||
context: context,
|
||||
barrierDismissible: true, // user must tap button!
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('存储'),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
TextField(
|
||||
decoration: const InputDecoration(labelText: "名称"),
|
||||
controller: nameController,
|
||||
),
|
||||
TextField(
|
||||
decoration: const InputDecoration(labelText: "实现"),
|
||||
controller: implController,
|
||||
),
|
||||
TextField(
|
||||
decoration: const InputDecoration(labelText: "路径"),
|
||||
controller: pathController,
|
||||
),
|
||||
TextField(
|
||||
decoration: const InputDecoration(labelText: "用户"),
|
||||
controller: userController,
|
||||
),
|
||||
TextField(
|
||||
decoration: const InputDecoration(labelText: "密码"),
|
||||
controller: passController,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
s.id == null
|
||||
? const Text("")
|
||||
: TextButton(
|
||||
onPressed: () {
|
||||
var f = ref
|
||||
.read(storageSettingProvider.notifier)
|
||||
.deleteStorage(s.id!);
|
||||
var nameController = TextEditingController(text: s.name);
|
||||
var pathController = TextEditingController();
|
||||
var urlController = TextEditingController();
|
||||
var userController = TextEditingController();
|
||||
var passController = TextEditingController();
|
||||
if (s.settings != null) {
|
||||
pathController.text = s.settings!["path"];
|
||||
urlController.text = s.settings!["url"];
|
||||
userController.text = s.settings!["user"];
|
||||
passController.text = s.settings!["password"];
|
||||
}
|
||||
|
||||
String _selectImpl = s.implementation == null? "local": s.implementation!;
|
||||
return StatefulBuilder(builder: (context, setState) {
|
||||
return AlertDialog(
|
||||
title: const Text('存储'),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: <Widget>[
|
||||
DropdownMenu(
|
||||
label: const Text("实现"),
|
||||
onSelected: (value) {
|
||||
setState(() {
|
||||
_pendingStorage = f;
|
||||
_selectImpl = value!;
|
||||
});
|
||||
if (!showError(snapshot)) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
child: const Text('删除')),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('取消')),
|
||||
TextButton(
|
||||
child: const Text('确定'),
|
||||
onPressed: () {
|
||||
var f = ref.read(storageSettingProvider.notifier).addStorage(
|
||||
Storage(
|
||||
name: nameController.text,
|
||||
implementation: implController.text,
|
||||
path: pathController.text,
|
||||
user: userController.text,
|
||||
password: passController.text));
|
||||
setState(() {
|
||||
_pendingStorage = f;
|
||||
});
|
||||
if (!showError(snapshot)) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
initialSelection: _selectImpl,
|
||||
dropdownMenuEntries: const [
|
||||
DropdownMenuEntry(value: "local", label: "本地存储"),
|
||||
DropdownMenuEntry(value: "webdav", label: "webdav")
|
||||
],
|
||||
),
|
||||
TextField(
|
||||
decoration: const InputDecoration(labelText: "名称"),
|
||||
controller: nameController,
|
||||
),
|
||||
_selectImpl == "local"
|
||||
? TextField(
|
||||
decoration: const InputDecoration(labelText: "路径"),
|
||||
controller: pathController,
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Webdav网址"),
|
||||
controller: urlController,
|
||||
),
|
||||
TextField(
|
||||
decoration:
|
||||
const InputDecoration(labelText: "用户"),
|
||||
controller: userController,
|
||||
),
|
||||
TextField(
|
||||
decoration:
|
||||
const InputDecoration(labelText: "密码"),
|
||||
controller: passController,
|
||||
),
|
||||
TextField(
|
||||
decoration:
|
||||
const InputDecoration(labelText: "路径"),
|
||||
controller: pathController,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
actions: <Widget>[
|
||||
s.id == null
|
||||
? const Text("")
|
||||
: TextButton(
|
||||
onPressed: () {
|
||||
var f = ref
|
||||
.read(storageSettingProvider.notifier)
|
||||
.deleteStorage(s.id!);
|
||||
setState(() {
|
||||
_pendingStorage = f;
|
||||
});
|
||||
if (!showError(snapshot)) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
child: const Text('删除')),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('取消')),
|
||||
TextButton(
|
||||
child: const Text('确定'),
|
||||
onPressed: () async {
|
||||
ref
|
||||
.read(storageSettingProvider.notifier)
|
||||
.addStorage(Storage(
|
||||
name: nameController.text,
|
||||
implementation: _selectImpl,
|
||||
settings: {
|
||||
"path": pathController.text,
|
||||
"url": urlController.text,
|
||||
"user": userController.text,
|
||||
"password": passController.text
|
||||
},
|
||||
));
|
||||
if (!showError(snapshot)) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user