mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-02-12 03:41:38 +00:00
Allow selection of multiple files (#600)
Some checks are pending
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage deb updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Some checks are pending
Build and Release / Read metadata (push) Waiting to run
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage deb updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis updater) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage deb updater) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
This commit is contained in:
parent
23594cdda6
commit
7a6b66c802
@ -127,17 +127,21 @@ public partial class AttachDocuments : MSGComponentBase
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedFile = await this.RustService.SelectFile(T("Select a file to attach"));
|
||||
if (selectedFile.UserCancelled)
|
||||
var selectFiles = await this.RustService.SelectFiles(T("Select a file to attach"));
|
||||
if (selectFiles.UserCancelled)
|
||||
return;
|
||||
|
||||
if (!File.Exists(selectedFile.SelectedFilePath))
|
||||
return;
|
||||
foreach (var selectedFilePath in selectFiles.SelectedFilePaths)
|
||||
{
|
||||
if (!File.Exists(selectedFilePath))
|
||||
continue;
|
||||
|
||||
if (!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(selectedFile.SelectedFilePath))
|
||||
return;
|
||||
if (!await FileExtensionValidation.IsExtensionValidWithNotifyAsync(selectedFilePath))
|
||||
return;
|
||||
|
||||
this.DocumentPaths.Add(selectedFilePath);
|
||||
}
|
||||
|
||||
this.DocumentPaths.Add(selectedFile.SelectedFilePath);
|
||||
await this.DocumentPathsChanged.InvokeAsync(this.DocumentPaths);
|
||||
await this.OnChange(this.DocumentPaths);
|
||||
}
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
namespace AIStudio.Tools.Rust;
|
||||
|
||||
/// <summary>
|
||||
/// Data structure for selecting multiple files.
|
||||
/// </summary>
|
||||
/// <param name="UserCancelled">Was the file selection canceled?</param>
|
||||
/// <param name="SelectedFilePaths">The selected files, if any.</param>
|
||||
public readonly record struct FilesSelectionResponse(bool UserCancelled, IReadOnlyList<string> SelectedFilePaths);
|
||||
@ -36,6 +36,25 @@ public sealed partial class RustService
|
||||
return await result.Content.ReadFromJsonAsync<FileSelectionResponse>(this.jsonRustSerializerOptions);
|
||||
}
|
||||
|
||||
public async Task<FilesSelectionResponse> SelectFiles(string title, FileTypeFilter? filter = null, string? initialFile = null)
|
||||
{
|
||||
var payload = new SelectFileOptions
|
||||
{
|
||||
Title = title,
|
||||
PreviousFile = initialFile is null ? null : new (initialFile),
|
||||
Filter = filter
|
||||
};
|
||||
|
||||
var result = await this.http.PostAsJsonAsync("/select/files", payload, this.jsonRustSerializerOptions);
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
this.logger!.LogError($"Failed to select files: '{result.StatusCode}'");
|
||||
return new FilesSelectionResponse(true, Array.Empty<string>());
|
||||
}
|
||||
|
||||
return await result.Content.ReadFromJsonAsync<FilesSelectionResponse>(this.jsonRustSerializerOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initiates a dialog to let the user select a file for a writing operation.
|
||||
/// </summary>
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
- Improved file reading, e.g. for the translation, summarization, and legal assistants, by performing the Pandoc validation in the first step. This prevents unnecessary selection of files that cannot be processed.
|
||||
- Improved the file selection for file attachments in chat and assistant file loading by filtering out audio files. Audio attachments are not yet supported.
|
||||
- Improved the developer experience by automating localization updates in the filesystem for the selected language in the localization assistant.
|
||||
- Improved the file selection so that users can now select multiple files at the same time. This is useful, for example, for document analysis (in preview) or adding file attachments to the chat.
|
||||
- Fixed a bug in the local data sources info dialog (preview feature) for data directories that could cause the app to crash. The error was caused by a background thread producing data while the frontend attempted to display it.
|
||||
- Fixed a visual bug where a function's preview status was misaligned. You might have seen it in document analysis or the ERI server assistant.
|
||||
- Fixed a rare bug in the Microsoft Word export for huge documents.
|
||||
|
||||
@ -561,6 +561,56 @@ pub fn select_file(_token: APIToken, payload: Json<SelectFileOptions>) -> Json<F
|
||||
}
|
||||
}
|
||||
|
||||
/// Let the user select some files.
|
||||
#[post("/select/files", data = "<payload>")]
|
||||
pub fn select_files(_token: APIToken, payload: Json<SelectFileOptions>) -> Json<FilesSelectionResponse> {
|
||||
|
||||
// Create a new file dialog builder:
|
||||
let file_dialog = FileDialogBuilder::new();
|
||||
|
||||
// Set the title of the file dialog:
|
||||
let file_dialog = file_dialog.set_title(&payload.title);
|
||||
|
||||
// Set the file type filter if provided:
|
||||
let file_dialog = match &payload.filter {
|
||||
Some(filter) => {
|
||||
file_dialog.add_filter(&filter.filter_name, &filter.filter_extensions.iter().map(|s| s.as_str()).collect::<Vec<&str>>())
|
||||
},
|
||||
|
||||
None => file_dialog,
|
||||
};
|
||||
|
||||
// Set the previous file path if provided:
|
||||
let file_dialog = match &payload.previous_file {
|
||||
Some(previous) => {
|
||||
let previous_path = previous.file_path.as_str();
|
||||
file_dialog.set_directory(previous_path)
|
||||
},
|
||||
|
||||
None => file_dialog,
|
||||
};
|
||||
|
||||
// Show the file dialog and get the selected file path:
|
||||
let file_paths = file_dialog.pick_files();
|
||||
match file_paths {
|
||||
Some(paths) => {
|
||||
info!("User selected {} files.", paths.len());
|
||||
Json(FilesSelectionResponse {
|
||||
user_cancelled: false,
|
||||
selected_file_paths: paths.iter().map(|p| p.to_str().unwrap().to_string()).collect(),
|
||||
})
|
||||
}
|
||||
|
||||
None => {
|
||||
info!("User cancelled file selection.");
|
||||
Json(FilesSelectionResponse {
|
||||
user_cancelled: true,
|
||||
selected_file_paths: Vec::new(),
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/save/file", data = "<payload>")]
|
||||
pub fn save_file(_token: APIToken, payload: Json<SaveFileOptions>) -> Json<FileSaveResponse> {
|
||||
|
||||
@ -620,6 +670,13 @@ pub struct FileSelectionResponse {
|
||||
user_cancelled: bool,
|
||||
selected_file_path: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FilesSelectionResponse {
|
||||
user_cancelled: bool,
|
||||
selected_file_paths: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FileSaveResponse {
|
||||
user_cancelled: bool,
|
||||
|
||||
@ -73,6 +73,7 @@ pub fn start_runtime_api() {
|
||||
crate::app_window::install_update,
|
||||
crate::app_window::select_directory,
|
||||
crate::app_window::select_file,
|
||||
crate::app_window::select_files,
|
||||
crate::app_window::save_file,
|
||||
crate::secret::get_secret,
|
||||
crate::secret::store_secret,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user