fix drag&drop for web
This commit is contained in:
parent
bba42586f3
commit
2ab73b1dc4
|
|
@ -1,12 +1,33 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
|
|
||||||
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
import 'src/app.dart';
|
import 'src/app.dart';
|
||||||
import 'src/settings/settings_controller.dart';
|
import 'src/settings/settings_controller.dart';
|
||||||
import 'src/settings/settings_service.dart';
|
import 'src/settings/settings_service.dart';
|
||||||
|
|
||||||
void main(List<String> args) async {
|
void main(List<String> args) async {
|
||||||
|
// Identify if Desktop or Mobile app.
|
||||||
|
|
||||||
|
if (!kIsWeb) {
|
||||||
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
await windowManager.ensureInitialized();
|
||||||
|
|
||||||
|
WindowOptions windowOptions = const WindowOptions(
|
||||||
|
title: 'Fast Log Viewer',
|
||||||
|
center: true,
|
||||||
|
);
|
||||||
|
|
||||||
|
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||||
|
await windowManager.show();
|
||||||
|
await windowManager.focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the SettingsController, which will glue user settings to multiple
|
// Set up the SettingsController, which will glue user settings to multiple
|
||||||
// Flutter Widgets.
|
// Flutter Widgets.
|
||||||
final settingsController = SettingsController(SettingsService());
|
final settingsController = SettingsController(SettingsService());
|
||||||
|
|
|
||||||
119
lib/src/app.dart
119
lib/src/app.dart
|
|
@ -72,11 +72,13 @@ class LogViewerScreen extends StatefulWidget {
|
||||||
class LogViewerScreenState extends State<LogViewerScreen> {
|
class LogViewerScreenState extends State<LogViewerScreen> {
|
||||||
List<LogEntry> logs = [];
|
List<LogEntry> logs = [];
|
||||||
List<LogEntry> visibleLogs = [];
|
List<LogEntry> visibleLogs = [];
|
||||||
String search = '';
|
|
||||||
LogLevel selectedLogLevel = LogLevel.info;
|
LogLevel selectedLogLevel = LogLevel.info;
|
||||||
bool _isDragging = false;
|
bool _isDragging = false;
|
||||||
|
|
||||||
|
TextEditingController controller = TextEditingController(text: '');
|
||||||
|
|
||||||
late SettingsController settingsController;
|
late SettingsController settingsController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
@ -93,9 +95,49 @@ class LogViewerScreenState extends State<LogViewerScreen> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Fast Log Viewer'),
|
|
||||||
actions: [
|
actions: [
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
controller: controller,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Search Logs',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_filterLogs();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DropdownButton<LogLevel>(
|
||||||
|
underline: Container(height: 0),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
value: selectedLogLevel,
|
||||||
|
onChanged: (LogLevel? newValue) {
|
||||||
|
if (newValue != null) {
|
||||||
|
setState(() {
|
||||||
|
selectedLogLevel = newValue;
|
||||||
|
_filterLogs();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
items: LogLevel.values
|
||||||
|
.map<DropdownMenuItem<LogLevel>>((LogLevel level) {
|
||||||
|
return DropdownMenuItem<LogLevel>(
|
||||||
|
value: level,
|
||||||
|
child: Text(level.name),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.folder_open),
|
||||||
|
onPressed: _openFile,
|
||||||
|
),
|
||||||
DropdownButton<ThemeMode>(
|
DropdownButton<ThemeMode>(
|
||||||
|
underline: Container(height: 0),
|
||||||
|
alignment: Alignment.center,
|
||||||
value: settingsController.themeMode,
|
value: settingsController.themeMode,
|
||||||
onChanged: (ThemeMode? newValue) async {
|
onChanged: (ThemeMode? newValue) async {
|
||||||
if (newValue != null) {
|
if (newValue != null) {
|
||||||
|
|
@ -120,10 +162,7 @@ class LogViewerScreenState extends State<LogViewerScreen> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
IconButton(
|
const SizedBox(width: 8),
|
||||||
icon: const Icon(Icons.folder_open),
|
|
||||||
onPressed: _openFile,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: DropTarget(
|
body: DropTarget(
|
||||||
|
|
@ -139,10 +178,10 @@ class LogViewerScreenState extends State<LogViewerScreen> {
|
||||||
},
|
},
|
||||||
onDragDone: (details) async {
|
onDragDone: (details) async {
|
||||||
if (details.files.isNotEmpty) {
|
if (details.files.isNotEmpty) {
|
||||||
File file = File(details.files.first.path);
|
var bytes = await details.files.first.readAsBytes();
|
||||||
String fileContent = await file.readAsString();
|
|
||||||
setState(() {
|
setState(() {
|
||||||
logs = _parseLogFile(fileContent);
|
logs = _parseLogFile(String.fromCharCodes(bytes));
|
||||||
|
controller.clear();
|
||||||
_filterLogs();
|
_filterLogs();
|
||||||
_isDragging = false;
|
_isDragging = false;
|
||||||
});
|
});
|
||||||
|
|
@ -154,46 +193,6 @@ class LogViewerScreenState extends State<LogViewerScreen> {
|
||||||
: Theme.of(context).scaffoldBackgroundColor,
|
: Theme.of(context).scaffoldBackgroundColor,
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(8.0),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: TextField(
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Search Logs',
|
|
||||||
border: OutlineInputBorder(),
|
|
||||||
),
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
search = value;
|
|
||||||
_filterLogs();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 8.0),
|
|
||||||
DropdownButton<LogLevel>(
|
|
||||||
value: selectedLogLevel,
|
|
||||||
onChanged: (LogLevel? newValue) {
|
|
||||||
if (newValue != null) {
|
|
||||||
setState(() {
|
|
||||||
selectedLogLevel = newValue;
|
|
||||||
_filterLogs();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
items: LogLevel.values
|
|
||||||
.map<DropdownMenuItem<LogLevel>>((LogLevel level) {
|
|
||||||
return DropdownMenuItem<LogLevel>(
|
|
||||||
value: level,
|
|
||||||
child: Text(level.name),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: SelectionArea(
|
child: SelectionArea(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
|
|
@ -215,14 +214,19 @@ class LogViewerScreenState extends State<LogViewerScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _openFile() async {
|
Future<void> _openFile() async {
|
||||||
FilePickerResult? result = await FilePicker.platform.pickFiles();
|
FilePickerResult? result =
|
||||||
|
await FilePicker.platform.pickFiles(withData: true);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
File file = File(result.files.single.path!);
|
if (result.files.isNotEmpty) {
|
||||||
String fileContent = await file.readAsString();
|
var bytes = result.files.first.bytes;
|
||||||
setState(() {
|
if (bytes != null) {
|
||||||
logs = _parseLogFile(fileContent);
|
setState(() {
|
||||||
_filterLogs();
|
logs = _parseLogFile(String.fromCharCodes(bytes));
|
||||||
});
|
controller.clear();
|
||||||
|
_filterLogs();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -230,7 +234,8 @@ class LogViewerScreenState extends State<LogViewerScreen> {
|
||||||
setState(() {
|
setState(() {
|
||||||
visibleLogs = logs
|
visibleLogs = logs
|
||||||
.where((log) =>
|
.where((log) =>
|
||||||
log.level.index >= selectedLogLevel.index && log.contains(search))
|
log.level.index >= selectedLogLevel.index &&
|
||||||
|
log.contains(controller.text))
|
||||||
.toList();
|
.toList();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,17 @@
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <desktop_drop/desktop_drop_plugin.h>
|
#include <desktop_drop/desktop_drop_plugin.h>
|
||||||
|
#include <screen_retriever/screen_retriever_plugin.h>
|
||||||
|
#include <window_manager/window_manager_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
g_autoptr(FlPluginRegistrar) desktop_drop_registrar =
|
g_autoptr(FlPluginRegistrar) desktop_drop_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin");
|
||||||
desktop_drop_plugin_register_with_registrar(desktop_drop_registrar);
|
desktop_drop_plugin_register_with_registrar(desktop_drop_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) screen_retriever_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "ScreenRetrieverPlugin");
|
||||||
|
screen_retriever_plugin_register_with_registrar(screen_retriever_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) window_manager_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowManagerPlugin");
|
||||||
|
window_manager_plugin_register_with_registrar(window_manager_registrar);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
desktop_drop
|
desktop_drop
|
||||||
|
screen_retriever
|
||||||
|
window_manager
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,13 @@ import FlutterMacOS
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
import desktop_drop
|
import desktop_drop
|
||||||
|
import screen_retriever
|
||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
|
import window_manager
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin"))
|
DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin"))
|
||||||
|
ScreenRetrieverPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverPlugin"))
|
||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
|
WindowManagerPlugin.register(with: registry.registrar(forPlugin: "WindowManagerPlugin"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
pubspec.lock
16
pubspec.lock
|
|
@ -237,6 +237,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.8"
|
version: "2.1.8"
|
||||||
|
screen_retriever:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: screen_retriever
|
||||||
|
sha256: "6ee02c8a1158e6dae7ca430da79436e3b1c9563c8cf02f524af997c201ac2b90"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.1.9"
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
|
@ -378,6 +386,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.5.5"
|
version: "5.5.5"
|
||||||
|
window_manager:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: window_manager
|
||||||
|
sha256: ab8b2a7f97543d3db2b506c9d875e637149d48ee0c6a5cb5f5fd6e0dac463792
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.4.2"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ dependencies:
|
||||||
file_picker:
|
file_picker:
|
||||||
desktop_drop:
|
desktop_drop:
|
||||||
shared_preferences:
|
shared_preferences:
|
||||||
|
window_manager:
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,14 @@
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <desktop_drop/desktop_drop_plugin.h>
|
#include <desktop_drop/desktop_drop_plugin.h>
|
||||||
|
#include <screen_retriever/screen_retriever_plugin.h>
|
||||||
|
#include <window_manager/window_manager_plugin.h>
|
||||||
|
|
||||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
DesktopDropPluginRegisterWithRegistrar(
|
DesktopDropPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
|
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
|
||||||
|
ScreenRetrieverPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
|
||||||
|
WindowManagerPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("WindowManagerPlugin"));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
desktop_drop
|
desktop_drop
|
||||||
|
screen_retriever
|
||||||
|
window_manager
|
||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue