Skip to main content

dxc_components/image/
image.rs

1use super::props::ImageProps;
2use crate::image_viewer::DxcImageViewer;
3use dioxus::prelude::*;
4use dxc_hooks::UseNamespace;
5use dxc_macros::classes;
6use dxc_types::{components::image::Loading, namespace::Block};
7
8#[component]
9pub fn DxcImage(props: ImageProps) -> Element {
10    let img_src = use_signal(|| props.src());
11    let alt = use_signal(|| props.alt());
12    let loading = use_signal(|| props.loading());
13    let lazy = use_signal(|| props.lazy());
14    let fit = use_signal(|| props.fit());
15    let initial_index = use_signal(|| props.initial_index());
16    let preview_src_list = use_signal(|| props.preview_src_list());
17    let crossorigin = use_signal(|| props.crossorigin());
18
19    let mut image_src = use_signal(|| String::new());
20
21    let mut has_load_error = use_signal(|| false);
22    let mut is_loading = use_signal(|| true);
23    let mut show_viewer = use_signal(|| false);
24    let support_loading = use_signal(|| false);
25    let preview = use_signal(|| preview_src_list.len() > 0);
26
27    let image_index = use_memo(move || {
28        let mut preview_index = initial_index();
29
30        if let Some(next) = preview_src_list().len().checked_sub(1) {
31            if initial_index() > next {
32                preview_index = 0;
33            }
34        }
35
36        preview_index
37    });
38
39    let is_manual = use_signal(|| {
40        if loading() == Loading::Lazy {
41            return false;
42        }
43
44        return !support_loading() && loading() == Loading::Lazy || lazy();
45    });
46
47    let mut laod_image = move || {
48        is_loading.set(true);
49        has_load_error.set(false);
50        image_src.set(img_src());
51    };
52
53    let handle_lazy_load = move || {
54        laod_image();
55    };
56
57    // use_before_render(|| {
58    //     if is_manual() {
59    //         handle_lazy_load();
60    //     }
61    // });
62
63    let ns = UseNamespace::new(Block::Image, None);
64
65    let image_classes = classes! {
66        ns.e_(String::from("inner")),
67        if preview() { &ns.e_(String::from("preview")) },
68        if is_loading() { &ns.e_(String::from("loading")) },
69    };
70
71    let image_style = format!("object-fit: {};", fit());
72
73    rsx! {
74        div {
75            class: ns.b(),
76
77            // if image load error, show error message slot
78            // else show image
79            if has_load_error() {
80                div {
81                    "name": "image_error",
82                    div {
83                        class: ns.e_(String::from("error")),
84                        "FAILED"
85                    }
86                    {props.error}
87                }
88            } else {
89                div {
90                    // if image src is set, show image
91                    // else show placeholder
92                    if !img_src().is_empty(){
93                        img {
94                            src: img_src(),
95                            alt: alt(),
96                            class: image_classes,
97                            style: image_style,
98                            loading: loading(),
99                            crossorigin: crossorigin(),
100                            onclick: move |_| {
101                                if !preview() {
102                                    return;
103                                }
104
105                                show_viewer.set(true);
106                            },
107                            onload: move |_| {
108                                is_loading.set(false);
109                                has_load_error.set(false);
110                            },
111                            onerror: move |_| {
112                                is_loading.set(false);
113                                has_load_error.set(true);
114                            },
115                        }
116                    }
117
118                    if is_loading() {
119                        div {
120                            class: ns.e_(String::from("wrapper")),
121                            div {
122                                class: ns.e_(String::from("placeholder")),
123                                {props.placeholder}
124                            }
125                        }
126                    }
127                }
128            }
129
130            if preview() {
131                if show_viewer() {
132                    DxcImageViewer{
133                        z_index: props.z_index,
134                        initial_index: image_index(),
135                        infinite: props.infinite,
136                        zoom_rate: props.zoom_rate,
137                        min_scale: props.min_scale,
138                        max_scale: props.max_scale,
139                        show_progress: props.show_progress,
140                        url_list: preview_src_list(),
141                        crossorigin: crossorigin(),
142                        // hide_on_cllick_modal: hide_on_click_modal,
143                        // teleported: preview_teleported(),
144                        // close_on_press_escape: close_on_press_escape,
145                        onclose: move |_| {
146                            show_viewer.set(false);
147                        },
148                        // on_switch: move |index| {
149                        //     // current_index.set(index);
150                        // },
151                    }
152                }
153            }
154        }
155    }
156}