mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-20 17:02:53 -04:00
fix delete (and add second button) (#995)
- delete hamburger icon fixed - delete button added to gallery - flows through tauri instead of javascript API - ondelete toast events (tauri sent, frontend consumed)
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
use crate::core::commands::response::shorthand::ResponseOrErrorMessage;
|
||||
use crate::core::commands::response::success_response_wrapper::SerializeMarker;
|
||||
use crate::core::events::basic_sendable_event_trait::BasicSendableEvent;
|
||||
use crate::core::events::functional_events::media_file_deleted_event::MediaFileDeletedEvent;
|
||||
use crate::core::events::generation_events::generation_enqueue_success_event::GenerationEnqueueSuccessEvent;
|
||||
use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs;
|
||||
use crate::core::state::data_dir::app_data_root::AppDataRoot;
|
||||
@@ -23,6 +25,7 @@ pub struct MediaFileDeleteRequest {
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct MediaFileDeleteSuccessResponse {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
impl SerializeMarker for MediaFileDeleteSuccessResponse {}
|
||||
@@ -49,7 +52,9 @@ pub async fn media_file_delete_command(
|
||||
return Err("delete failed".into())
|
||||
}
|
||||
|
||||
Ok(MediaFileDeleteSuccessResponse{}.into())
|
||||
Ok(MediaFileDeleteSuccessResponse {
|
||||
success: true,
|
||||
}.into())
|
||||
}
|
||||
|
||||
pub async fn handle_request(
|
||||
@@ -67,7 +72,9 @@ pub async fn handle_request(
|
||||
&request.media_file_token
|
||||
).await?;
|
||||
|
||||
// TODO: Send event to frontend that the file was deleted.
|
||||
MediaFileDeletedEvent {
|
||||
media_file_token: request.media_file_token,
|
||||
}.send_infallible(app);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
use crate::core::events::basic_sendable_event_trait::{BasicEventStatus, BasicSendableEvent};
|
||||
use enums::tauri::ux::tauri_event_name::TauriEventName;
|
||||
use serde_derive::Serialize;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use url::Url;
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub struct MediaFileDeletedEvent {
|
||||
pub media_file_token: MediaFileToken,
|
||||
}
|
||||
|
||||
impl BasicSendableEvent for MediaFileDeletedEvent {
|
||||
const FRONTEND_EVENT_NAME: TauriEventName = TauriEventName::MediaFileDeletedEvent;
|
||||
const EVENT_STATUS: BasicEventStatus = BasicEventStatus::Success;
|
||||
}
|
||||
@@ -2,6 +2,7 @@ pub mod canvas_background_removal_complete_event;
|
||||
pub mod credits_balance_changed_event;
|
||||
pub mod gaussian_generation_complete_event;
|
||||
pub mod image_edit_complete_event;
|
||||
pub mod media_file_deleted_event;
|
||||
pub mod object_generation_complete_event;
|
||||
pub mod refresh_account_state_event;
|
||||
pub mod show_provider_billing_modal_event;
|
||||
|
||||
@@ -48,8 +48,13 @@ pub enum TauriEventName {
|
||||
#[serde(rename = "subscription_plan_changed_event")]
|
||||
SubscriptionPlanChangedEvent,
|
||||
|
||||
/// Informational event:
|
||||
/// A media file was deleted (and we'll send the token)
|
||||
#[serde(rename = "media_file_deleted_event")]
|
||||
MediaFileDeletedEvent,
|
||||
|
||||
/// Special event:
|
||||
/// Background removal complete
|
||||
/// Background removal is complete
|
||||
#[serde(rename = "canvas_bg_removed_event")]
|
||||
CanvasBgRemovedEvent,
|
||||
|
||||
@@ -119,6 +124,7 @@ impl TauriEventName {
|
||||
Self::GenerationFailedEvent => "generation-failed-event",
|
||||
Self::CreditsBalanceChangedEvent => "credits_balance_changed_event",
|
||||
Self::SubscriptionPlanChangedEvent => "subscription_plan_changed_event",
|
||||
Self::MediaFileDeletedEvent => "media_file_deleted_event",
|
||||
Self::CanvasBgRemovedEvent => "canvas_bg_removed_event",
|
||||
Self::TextToImageGenerationCompleteEvent => "text_to_image_generation_complete_event",
|
||||
Self::ImageEditCompleteEvent => "image_edit_complete_event",
|
||||
@@ -141,6 +147,7 @@ impl TauriEventName {
|
||||
"generation-failed-event" => Ok(Self::GenerationFailedEvent),
|
||||
"credits_balance_changed_event" => Ok(Self::CreditsBalanceChangedEvent),
|
||||
"subscription_plan_changed_event" => Ok(Self::SubscriptionPlanChangedEvent),
|
||||
"media_file_deleted_event" => Ok(Self::MediaFileDeletedEvent),
|
||||
"canvas_bg_removed_event" => Ok(Self::CanvasBgRemovedEvent),
|
||||
"text_to_image_generation_complete_event" => Ok(Self::TextToImageGenerationCompleteEvent),
|
||||
"image_edit_complete_event" => Ok(Self::ImageEditCompleteEvent),
|
||||
@@ -166,6 +173,7 @@ impl TauriEventName {
|
||||
Self::GenerationFailedEvent,
|
||||
Self::CreditsBalanceChangedEvent,
|
||||
Self::SubscriptionPlanChangedEvent,
|
||||
Self::MediaFileDeletedEvent,
|
||||
Self::CanvasBgRemovedEvent,
|
||||
Self::TextToImageGenerationCompleteEvent,
|
||||
Self::ImageEditCompleteEvent,
|
||||
@@ -197,6 +205,7 @@ mod tests {
|
||||
assert_serialization(TauriEventName::GenerationFailedEvent, "generation-failed-event");
|
||||
assert_serialization(TauriEventName::CreditsBalanceChangedEvent, "credits_balance_changed_event");
|
||||
assert_serialization(TauriEventName::SubscriptionPlanChangedEvent, "subscription_plan_changed_event");
|
||||
assert_serialization(TauriEventName::MediaFileDeletedEvent, "media_file_deleted_event");
|
||||
assert_serialization(TauriEventName::CanvasBgRemovedEvent, "canvas_bg_removed_event");
|
||||
assert_serialization(TauriEventName::TextToImageGenerationCompleteEvent, "text_to_image_generation_complete_event");
|
||||
assert_serialization(TauriEventName::ImageEditCompleteEvent, "image_edit_complete_event");
|
||||
@@ -218,6 +227,7 @@ mod tests {
|
||||
assert_eq!(TauriEventName::GenerationFailedEvent.to_str(), "generation-failed-event");
|
||||
assert_eq!(TauriEventName::CreditsBalanceChangedEvent.to_str(), "credits_balance_changed_event");
|
||||
assert_eq!(TauriEventName::SubscriptionPlanChangedEvent.to_str(), "subscription_plan_changed_event");
|
||||
assert_eq!(TauriEventName::MediaFileDeletedEvent.to_str(), "media_file_deleted_event");
|
||||
assert_eq!(TauriEventName::CanvasBgRemovedEvent.to_str(), "canvas_bg_removed_event");
|
||||
assert_eq!(TauriEventName::TextToImageGenerationCompleteEvent.to_str(), "text_to_image_generation_complete_event");
|
||||
assert_eq!(TauriEventName::ImageEditCompleteEvent.to_str(), "image_edit_complete_event");
|
||||
@@ -239,6 +249,7 @@ mod tests {
|
||||
assert_eq!(TauriEventName::from_str("generation-failed-event").unwrap(), TauriEventName::GenerationFailedEvent);
|
||||
assert_eq!(TauriEventName::from_str("credits_balance_changed_event").unwrap(), TauriEventName::CreditsBalanceChangedEvent);
|
||||
assert_eq!(TauriEventName::from_str("subscription_plan_changed_event").unwrap(), TauriEventName::SubscriptionPlanChangedEvent);
|
||||
assert_eq!(TauriEventName::from_str("media_file_deleted_event").unwrap(), TauriEventName::MediaFileDeletedEvent);
|
||||
assert_eq!(TauriEventName::from_str("canvas_bg_removed_event").unwrap(), TauriEventName::CanvasBgRemovedEvent);
|
||||
assert_eq!(TauriEventName::from_str("text_to_image_generation_complete_event").unwrap(), TauriEventName::TextToImageGenerationCompleteEvent);
|
||||
assert_eq!(TauriEventName::from_str("image_edit_complete_event").unwrap(), TauriEventName::ImageEditCompleteEvent);
|
||||
@@ -255,13 +266,14 @@ mod tests {
|
||||
#[test]
|
||||
fn all_variants() {
|
||||
let mut variants = TauriEventName::all_variants();
|
||||
assert_eq!(variants.len(), 17);
|
||||
assert_eq!(variants.len(), 18);
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::GenerationEnqueueSuccessEvent));
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::GenerationEnqueueFailureEvent));
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::GenerationCompleteEvent));
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::GenerationFailedEvent));
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::CreditsBalanceChangedEvent));
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::SubscriptionPlanChangedEvent));
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::MediaFileDeletedEvent));
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::CanvasBgRemovedEvent));
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::TextToImageGenerationCompleteEvent));
|
||||
assert_eq!(variants.pop_first(), Some(TauriEventName::ImageEditCompleteEvent));
|
||||
|
||||
@@ -42,8 +42,8 @@ GC_ENABLED_PUBLIC_BUCKET_NAME="REPLACE_ME"
|
||||
AUDIO_UPLOADS_BUCKET_ROOT=/user_uploaded_w2l_audio
|
||||
|
||||
# Fake API key for FAL
|
||||
#FAL_WEBHOOK_URL="https://macaroni-1.tailce84f.ts.net/v1/webhooks/fal"
|
||||
FAL_WEBHOOK_URL="https://halide.tailce84f.ts.net/v1/webhooks/fal"
|
||||
FAL_WEBHOOK_URL="https://macaroni-1.tailce84f.ts.net/v1/webhooks/fal"
|
||||
#FAL_WEBHOOK_URL="https://halide.tailce84f.ts.net/v1/webhooks/fal"
|
||||
#FAL_WEBHOOK_URL="https://s1.pancake-chimaera.ts.net/api/fal/webhook"
|
||||
|
||||
STRIPE_ARTCRAFT_CHECKOUT_SUCCESS_URL="https://getartcraft.com/checkout_success"
|
||||
|
||||
@@ -42,39 +42,6 @@ interface SearchFeaturedMediaQuery {
|
||||
}
|
||||
|
||||
export class MediaFilesApi extends ApiManager {
|
||||
public async DeleteMediaFileByToken({
|
||||
mediaFileToken,
|
||||
asMod = true,
|
||||
setDelete = true,
|
||||
}: {
|
||||
mediaFileToken: string;
|
||||
asMod?: boolean;
|
||||
setDelete?: boolean;
|
||||
}): Promise<ApiResponse<MediaFile>> {
|
||||
const endpoint = `${this.getApiSchemeAndHost()}/v1/media_files/file/${mediaFileToken}`;
|
||||
|
||||
const body = { as_mod: asMod, set_delete: setDelete };
|
||||
return await this.delete<
|
||||
{
|
||||
as_mod: boolean;
|
||||
set_delete: boolean;
|
||||
},
|
||||
{
|
||||
success?: boolean;
|
||||
BadInput?: string;
|
||||
}
|
||||
>({ endpoint, body })
|
||||
.then((response) => ({
|
||||
success: response.success ?? false,
|
||||
errorMessage: response.BadInput,
|
||||
}))
|
||||
.catch((err) => {
|
||||
return {
|
||||
success: false,
|
||||
errorMessage: err.message,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public async ListMediaFilesByTokens({
|
||||
mediaTokens,
|
||||
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
actionReminderProps,
|
||||
ActionReminderModal,
|
||||
} from "@storyteller/ui-action-reminder-modal";
|
||||
import { useFlashFileDownloadErrorEvent, useFlashUserInputErrorEvent } from "@storyteller/tauri-events";
|
||||
import { useFlashFileDownloadErrorEvent, useFlashUserInputErrorEvent, useMediaFileDeletedEvent } from "@storyteller/tauri-events";
|
||||
import { useGenerationCompleteEvent } from "@storyteller/tauri-events";
|
||||
import { useGenerationEnqueueFailureEvent } from "@storyteller/tauri-events";
|
||||
import { useGenerationEnqueueSuccessEvent } from "@storyteller/tauri-events";
|
||||
@@ -115,6 +115,11 @@ export const PageEnigma = ({ sceneToken }: { sceneToken?: string }) => {
|
||||
toast.error(event.message || "File download failed");
|
||||
});
|
||||
|
||||
useMediaFileDeletedEvent(async (event) => {
|
||||
console.log("Media file deleted event received:", event);
|
||||
toast.error("File deleted.");
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
console.log("installing event listeners");
|
||||
InstallSounds();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useMemo, useRef } from "react";
|
||||
import React, { useRef } from "react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import {
|
||||
faCheck,
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
showActionReminder,
|
||||
isActionReminderOpen,
|
||||
} from "@storyteller/ui-action-reminder-modal";
|
||||
import { MediaFilesApi } from "@storyteller/api";
|
||||
import { MediaFileDelete } from "@storyteller/tauri-api";
|
||||
|
||||
type ModalMode = "select" | "view";
|
||||
@@ -49,7 +48,6 @@ export const GalleryDraggableItem: React.FC<GalleryDraggableItemProps> = ({
|
||||
}) => {
|
||||
const imgRef = useRef<HTMLImageElement>(null);
|
||||
const dragStarted = useRef(false);
|
||||
const mediaFilesApi = useMemo(() => new MediaFilesApi(), []);
|
||||
|
||||
const handleDelete = () => {
|
||||
showActionReminder({
|
||||
@@ -65,16 +63,9 @@ export const GalleryDraggableItem: React.FC<GalleryDraggableItemProps> = ({
|
||||
secondaryActionText: "Cancel",
|
||||
primaryActionBtnClassName: "bg-red text-white hover:bg-red/90",
|
||||
onPrimaryAction: async () => {
|
||||
console.log(">>> Delete media file via Tauri: ", item.id);
|
||||
try {
|
||||
await MediaFileDelete(item.id);
|
||||
onDeleted?.(item.id);
|
||||
//const res = await mediaFilesApi.DeleteMediaFileByToken({
|
||||
// mediaFileToken: item.id,
|
||||
//});
|
||||
//if (res.success) {
|
||||
// onDeleted?.(item.id);
|
||||
//}
|
||||
} finally {
|
||||
isActionReminderOpen.value = false;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
import {
|
||||
EnqueueImageTo3dObject,
|
||||
EnqueueImageTo3dObjectModel,
|
||||
MediaFileDelete,
|
||||
} from "@storyteller/tauri-api";
|
||||
import { LoadingSpinner } from "@storyteller/ui-loading-spinner";
|
||||
import { Viewer3D } from "@storyteller/ui-viewer-3d";
|
||||
@@ -29,6 +30,10 @@ import { toast } from "@storyteller/ui-toaster";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faCopy, faLink, faCheck } from "@fortawesome/pro-solid-svg-icons";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
import {
|
||||
showActionReminder,
|
||||
isActionReminderOpen,
|
||||
} from "@storyteller/ui-action-reminder-modal";
|
||||
import {
|
||||
getModelCreatorIcon,
|
||||
getModelDisplayName,
|
||||
@@ -308,6 +313,30 @@ export function LightboxModal({
|
||||
[emblaMainApi, emblaThumbsApi],
|
||||
);
|
||||
|
||||
const onDeleteClicked = (mediaToken: string) => {
|
||||
showActionReminder({
|
||||
reminderType: "default",
|
||||
title: "Delete this media?",
|
||||
message: (
|
||||
<p className="text-sm text-white/70">
|
||||
This will permanently remove the media from your library. This action
|
||||
cannot be undone.
|
||||
</p>
|
||||
),
|
||||
primaryActionText: "Delete",
|
||||
secondaryActionText: "Cancel",
|
||||
primaryActionBtnClassName: "bg-red text-white hover:bg-red/90",
|
||||
onPrimaryAction: async () => {
|
||||
try {
|
||||
await MediaFileDelete(mediaToken);
|
||||
} finally {
|
||||
isActionReminderOpen.value = false;
|
||||
onClose();
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const onSelect = useCallback(() => {
|
||||
if (!emblaMainApi || !emblaThumbsApi) return;
|
||||
const index = emblaMainApi.selectedScrollSnap();
|
||||
@@ -803,7 +832,7 @@ export function LightboxModal({
|
||||
|
||||
{selectedMediaToken && (
|
||||
<Button
|
||||
className="w-full col-span-2"
|
||||
className="w-full"
|
||||
variant="secondary"
|
||||
icon={shareCopied ? faCheck : faLink}
|
||||
onClick={async (e) => {
|
||||
@@ -829,7 +858,21 @@ export function LightboxModal({
|
||||
}
|
||||
}}
|
||||
>
|
||||
{shareCopied ? "Link Copied!" : "Copy Share Link"}
|
||||
{shareCopied ? "Link Copied!" : "Share"}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{selectedMediaToken && onDeleteClicked && (
|
||||
<Button
|
||||
className="w-full"
|
||||
variant="destructive"
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation();
|
||||
gtagEvent("delete_media_clicked");
|
||||
await onDeleteClicked(selectedMediaToken);
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
export * from "./lib/artcraft/ArtcraftGetCredits.js";
|
||||
export * from "./lib/artcraft/ArtcraftGetSubscription.js";
|
||||
export * from "./lib/artcraft/media_files/MediaFileDelete.js";
|
||||
export * from "./lib/artcraft/task_queue/GetTaskQueue.js";
|
||||
export * from "./lib/artcraft/task_queue/MarkTaskAsDismissed.js";
|
||||
export * from "./lib/artcraft/task_queue/TasksNukeAll.js";
|
||||
@@ -23,9 +22,11 @@ export * from "./lib/fal/FalKlingImageToVideo.js";
|
||||
export * from "./lib/fal/GetFalApiKey.js";
|
||||
export * from "./lib/fal/SetFalApiKey.js";
|
||||
export * from "./lib/grok/GrokGetCredentialInfo.js";
|
||||
export * from "./lib/media_files/MediaFileDeleteCommand.js";
|
||||
export * from "./lib/midjourney/MidjourneyGetCredentialInfo.js";
|
||||
export * from "./lib/openai/GetOpenAIApiKey.js";
|
||||
export * from "./lib/openai/SetOpenAIApiKey.js";
|
||||
export * from "./lib/opener/OpenUrl.js";
|
||||
export * from "./lib/providers/GetProviderOrder.js";
|
||||
export * from "./lib/providers/Provider.js";
|
||||
export * from "./lib/providers/SetProviderOrder.js";
|
||||
@@ -39,5 +40,4 @@ export * from "./lib/sora/useSoraLoginListener.js";
|
||||
export * from "./lib/sora/waitForSoraLogin.js";
|
||||
export * from "./lib/system/GetAppInfo.js";
|
||||
export * from "./lib/util/LoadWithoutCors.js";
|
||||
export * from "./lib/worldlabs/WorldLabsGetCredentialInfo.js";
|
||||
export * from "./lib/opener/OpenUrl.js";
|
||||
export * from "./lib/worldlabs/WorldLabsGetCredentialInfo.js";
|
||||
@@ -1,21 +0,0 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { CommandResult } from "../../common/CommandStatus";
|
||||
|
||||
export interface MediaFileDeleteSuccess extends CommandResult {
|
||||
payload: MediaFileDeletePayload;
|
||||
}
|
||||
|
||||
export interface MediaFileDeletePayload {
|
||||
}
|
||||
|
||||
export const MediaFileDelete = async (media_file_token: string) : Promise<MediaFileDeleteSuccess> => {
|
||||
try {
|
||||
return await invoke("media_file_delete_command", {
|
||||
request: {
|
||||
media_file_token: media_file_token
|
||||
}
|
||||
}) as MediaFileDeleteSuccess;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { CommandResult } from "../common/CommandStatus";
|
||||
|
||||
export interface MediaFileDeleteError extends CommandResult {
|
||||
error_message?: string;
|
||||
}
|
||||
|
||||
export interface MediaFileDeletePayload {
|
||||
success: boolean;
|
||||
}
|
||||
|
||||
export interface MediaFileDeleteSuccess extends CommandResult {
|
||||
payload: MediaFileDeletePayload;
|
||||
}
|
||||
|
||||
export type MediaFileDeleteResult = MediaFileDeleteSuccess | MediaFileDeleteError;
|
||||
|
||||
export const MediaFileDelete = async (media_file_token: string) : Promise<MediaFileDeleteResult> => {
|
||||
const result = await invoke("media_file_delete_command", {
|
||||
request: {
|
||||
media_file_token: media_file_token,
|
||||
}
|
||||
});
|
||||
|
||||
return (result as MediaFileDeleteResult);
|
||||
}
|
||||
@@ -1,16 +1,17 @@
|
||||
export * from "./lib/common/BasicEventWrapper";
|
||||
export * from "./lib/events/functional/CreditsBalanceChangedEvent";
|
||||
export * from "./lib/events/functional/ImageEditCompleteEvent";
|
||||
export * from "./lib/events/functional/MediaFileDeletedEvent";
|
||||
export * from "./lib/events/functional/ObjectGenerationCompleteEvent";
|
||||
export * from "./lib/events/functional/RefreshAccountStateEvent";
|
||||
export * from "./lib/events/functional/ShowProviderBillingModalEvent";
|
||||
export * from "./lib/events/functional/ShowProviderLoginModalEvent";
|
||||
export * from "./lib/events/functional/TextToImageGenerationCompleteEvent";
|
||||
export * from "./lib/events/functional/ObjectGenerationCompleteEvent";
|
||||
export * from "./lib/events/functional/VideoGenerationCompleteEvent";
|
||||
export * from "./lib/events/functional/SubscriptionPlanChangedEvent";
|
||||
export * from "./lib/events/functional/TextToImageGenerationCompleteEvent";
|
||||
export * from "./lib/events/functional/VideoGenerationCompleteEvent";
|
||||
export * from "./lib/events/generation/useGenerationCompleteEvent";
|
||||
export * from "./lib/events/generation/useGenerationEnqueueFailureEvent";
|
||||
export * from "./lib/events/generation/useGenerationEnqueueSuccessEvent";
|
||||
export * from "./lib/events/generation/useGenerationFailedEvent";
|
||||
export * from "./lib/events/warning/FlashUserInputErrorEvent";
|
||||
export * from "./lib/events/warning/FlashFileDownloadErrorEvent";
|
||||
export * from "./lib/events/warning/FlashUserInputErrorEvent";
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { listen, UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { BasicEventWrapper } from "../../common/BasicEventWrapper";
|
||||
import { useEffect } from "react";
|
||||
|
||||
const EVENT_NAME: string = "media_file_deleted_event";
|
||||
|
||||
export interface MediaFileDeletedEvent {
|
||||
media_file_token: string;
|
||||
}
|
||||
|
||||
export const useMediaFileDeletedEvent = (
|
||||
asyncCallback: (event: MediaFileDeletedEvent) => Promise<void>
|
||||
) => {
|
||||
useEffect(() => {
|
||||
let isUnmounted = false;
|
||||
let unlisten: Promise<UnlistenFn>;
|
||||
|
||||
const setup = async () => {
|
||||
unlisten = listen<BasicEventWrapper<MediaFileDeletedEvent>>(
|
||||
EVENT_NAME,
|
||||
async (wrappedEvent) => {
|
||||
await asyncCallback(wrappedEvent.payload.data);
|
||||
}
|
||||
);
|
||||
|
||||
if (isUnmounted) {
|
||||
unlisten.then((f) => f()); // Unsubscribe if unmounted early.
|
||||
}
|
||||
};
|
||||
|
||||
setup();
|
||||
|
||||
return () => {
|
||||
isUnmounted = true;
|
||||
unlisten.then((f) => f());
|
||||
};
|
||||
}, []);
|
||||
};
|
||||
Reference in New Issue
Block a user