fix: Windows drag-and-drop via desktop_drop, sticky upload modal header, and Inactive student status

This commit is contained in:
ssbg04 committed 2026-07-25 22:11:12 +08:00
1 parent 652716de43
commit e4843606c1
7 files changed
+67 -24

No files matched your search

@@ -3,6 +3,7 @@ import 'dart:io';
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, TargetPlatform;
import 'package:flutter/material.dart';
import 'package:desktop_drop/desktop_drop.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../../core/constants/app_colors.dart';
import '../../../domain/entities/folder_model.dart';
@@ -1025,34 +1026,32 @@ class _DocumentsScreenState extends ConsumerState<DocumentsScreen>
final isWindows = defaultTargetPlatform == TargetPlatform.windows;
if (!isWindows) return child;
return DragTarget<String>(
onWillAcceptWithDetails: (details) {
setState(() => _isDragOver = true);
return true;
},
onLeave: (_) => setState(() => _isDragOver = false),
onAcceptWithDetails: (details) {
return DropTarget(
onDragEntered: (details) => setState(() => _isDragOver = true),
onDragExited: (details) => setState(() => _isDragOver = false),
onDragDone: (details) {
setState(() => _isDragOver = false);
final path = details.data;
final file = File(path);
final ext = path.toLowerCase();
if (ext.endsWith('.pdf') ||
ext.endsWith('.jpg') ||
ext.endsWith('.jpeg') ||
ext.endsWith('.png')) {
final validFiles = details.files.where((xfile) {
final ext = xfile.path.toLowerCase();
return ext.endsWith('.pdf') ||
ext.endsWith('.jpg') ||
ext.endsWith('.jpeg') ||
ext.endsWith('.png');
}).map((x) => File(x.path)).toList();
if (validFiles.isNotEmpty) {
UploadOcrModal.show(
context,
prefilledStudentId:
_openedFolderStudentId ?? widget.initialStudentId,
preloadedFiles: [file],
preloadedFiles: validFiles,
);
}
},
builder: (context, candidateData, rejectedData) {
return Stack(
children: [
child,
if (_isDragOver)
child: Stack(
children: [
child,
if (_isDragOver)
Positioned.fill(
child: IgnorePointer(
child: AnimatedContainer(
@@ -1100,8 +1099,7 @@ class _DocumentsScreenState extends ConsumerState<DocumentsScreen>
),
),
],
);
},
),
);
}
@@ -70,8 +70,8 @@ class UploadOcrModal extends ConsumerStatefulWidget {
WoltModalSheetPage(
backgroundColor: AppColors.surfaceWhite,
hasSabGradient: false,
hasTopBarLayer: false,
isTopBarLayerAlwaysVisible: false,
hasTopBarLayer: true,
isTopBarLayerAlwaysVisible: true,
child: UploadOcrModal(
prefilledStudentId: prefilledStudentId,
preloadedFiles: preloadedFiles,
@@ -56,6 +56,7 @@ class _StudentsScreenState extends ConsumerState<StudentsScreen> {
'Graduated',
'Transferred',
'Dropped',
'Inactive',
];
static const _4psItems = ['All', 'Yes', 'No'];
static const _pageSizes = [10, 20, 50];
@@ -284,6 +285,19 @@ class _StudentsScreenState extends ConsumerState<StudentsScreen> {
shape: const StadiumBorder(),
),
),
const SizedBox(width: 8),
ElevatedButton.icon(
onPressed: count == 0
? null
: () => _showBulkChangeStatusConfirm('Inactive', allStudents),
icon: const Icon(Icons.do_not_disturb_on_total_silence, size: 18),
label: const Text('Inactive'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blueGrey,
foregroundColor: Colors.white,
shape: const StadiumBorder(),
),
),
] else ...[
IconButton(
onPressed: count == 0 ? null : _showBulkEnrollModal,
@@ -324,6 +338,16 @@ class _StudentsScreenState extends ConsumerState<StudentsScreen> {
),
tooltip: 'Drop',
),
IconButton(
onPressed: count == 0
? null
: () => _showBulkChangeStatusConfirm('Inactive', allStudents),
icon: Icon(
Icons.do_not_disturb_on_total_silence,
color: count == 0 ? Colors.grey : Colors.blueGrey,
),
tooltip: 'Inactive',
),
],
const SizedBox(width: 4),
Container(
+16
View File
@@ -241,6 +241,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.7.14"
desktop_drop:
dependency: "direct main"
description:
name: desktop_drop
sha256: aa1e797255bfbc76f9eb5aa4f61e5b68dbf69962ab1be6495816d2f251bc0d1f
url: "https://pub.dev"
source: hosted
version: "0.7.1"
device_info_plus:
dependency: transitive
description:
@@ -1381,6 +1389,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.3.1"
universal_platform:
dependency: transitive
description:
name: universal_platform
sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
url_launcher:
dependency: "direct main"
description:
+1
View File
@@ -61,6 +61,7 @@ dependencies:
intl: ^0.20.3
flutter_local_notifications: ^17.2.2
workmanager: ^0.9.0+3
desktop_drop: ^0.7.1
dev_dependencies:
flutter_test:
@@ -6,6 +6,7 @@
#include "generated_plugin_registrant.h"
#include <desktop_drop/desktop_drop_plugin.h>
#include <file_selector_windows/file_selector_windows.h>
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
#include <permission_handler_windows/permission_handler_windows_plugin.h>
@@ -16,6 +17,8 @@
#include <window_manager/window_manager_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
DesktopDropPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("DesktopDropPlugin"));
FileSelectorWindowsRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FileSelectorWindows"));
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
@@ -3,6 +3,7 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
desktop_drop
file_selector_windows
flutter_secure_storage_windows
permission_handler_windows