Purify Animation API and introduce application::timed
This commit is contained in:
parent
4334923add
commit
29a19fcde1
9 changed files with 281 additions and 104 deletions
|
|
@ -21,14 +21,15 @@ use iced::{
|
|||
use std::collections::HashMap;
|
||||
|
||||
fn main() -> iced::Result {
|
||||
iced::application(Gallery::new, Gallery::update, Gallery::view)
|
||||
.window_size((
|
||||
Preview::WIDTH as f32 * 4.0,
|
||||
Preview::HEIGHT as f32 * 2.5,
|
||||
))
|
||||
.subscription(Gallery::subscription)
|
||||
.theme(Gallery::theme)
|
||||
.run()
|
||||
iced::application::timed(
|
||||
Gallery::new,
|
||||
Gallery::update,
|
||||
Gallery::subscription,
|
||||
Gallery::view,
|
||||
)
|
||||
.window_size((Preview::WIDTH as f32 * 4.0, Preview::HEIGHT as f32 * 2.5))
|
||||
.theme(Gallery::theme)
|
||||
.run()
|
||||
}
|
||||
|
||||
struct Gallery {
|
||||
|
|
@ -48,7 +49,7 @@ enum Message {
|
|||
BlurhashDecoded(Id, civitai::Blurhash),
|
||||
Open(Id),
|
||||
Close,
|
||||
Animate(Instant),
|
||||
Animate,
|
||||
}
|
||||
|
||||
impl Gallery {
|
||||
|
|
@ -76,13 +77,15 @@ impl Gallery {
|
|||
|| self.viewer.is_animating(self.now);
|
||||
|
||||
if is_animating {
|
||||
window::frames().map(Message::Animate)
|
||||
window::frames().map(|_| Message::Animate)
|
||||
} else {
|
||||
Subscription::none()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, message: Message) -> Task<Message> {
|
||||
pub fn update(&mut self, message: Message, now: Instant) -> Task<Message> {
|
||||
self.now = now;
|
||||
|
||||
match message {
|
||||
Message::ImagesListed(Ok(images)) => {
|
||||
self.images = images;
|
||||
|
|
@ -109,16 +112,16 @@ impl Gallery {
|
|||
)
|
||||
}
|
||||
Message::ImageDownloaded(Ok(rgba)) => {
|
||||
self.viewer.show(rgba);
|
||||
self.viewer.show(rgba, self.now);
|
||||
|
||||
Task::none()
|
||||
}
|
||||
Message::ThumbnailDownloaded(id, Ok(rgba)) => {
|
||||
let thumbnail = if let Some(preview) = self.previews.remove(&id)
|
||||
{
|
||||
preview.load(rgba)
|
||||
preview.load(rgba, self.now)
|
||||
} else {
|
||||
Preview::ready(rgba)
|
||||
Preview::ready(rgba, self.now)
|
||||
};
|
||||
|
||||
let _ = self.previews.insert(id, thumbnail);
|
||||
|
|
@ -127,7 +130,7 @@ impl Gallery {
|
|||
}
|
||||
Message::ThumbnailHovered(id, is_hovered) => {
|
||||
if let Some(preview) = self.previews.get_mut(&id) {
|
||||
preview.toggle_zoom(is_hovered);
|
||||
preview.toggle_zoom(is_hovered, self.now);
|
||||
}
|
||||
|
||||
Task::none()
|
||||
|
|
@ -136,7 +139,7 @@ impl Gallery {
|
|||
if !self.previews.contains_key(&id) {
|
||||
let _ = self
|
||||
.previews
|
||||
.insert(id, Preview::loading(blurhash.rgba));
|
||||
.insert(id, Preview::loading(blurhash.rgba, self.now));
|
||||
}
|
||||
|
||||
Task::none()
|
||||
|
|
@ -151,7 +154,7 @@ impl Gallery {
|
|||
return Task::none();
|
||||
};
|
||||
|
||||
self.viewer.open();
|
||||
self.viewer.open(self.now);
|
||||
|
||||
Task::perform(
|
||||
image.download(Size::Original),
|
||||
|
|
@ -159,15 +162,11 @@ impl Gallery {
|
|||
)
|
||||
}
|
||||
Message::Close => {
|
||||
self.viewer.close();
|
||||
|
||||
Task::none()
|
||||
}
|
||||
Message::Animate(now) => {
|
||||
self.now = now;
|
||||
self.viewer.close(self.now);
|
||||
|
||||
Task::none()
|
||||
}
|
||||
Message::Animate => Task::none(),
|
||||
Message::ImagesListed(Err(error))
|
||||
| Message::ImageDownloaded(Err(error))
|
||||
| Message::ThumbnailDownloaded(_, Err(error)) => {
|
||||
|
|
@ -293,13 +292,13 @@ impl Preview {
|
|||
const WIDTH: u32 = 320;
|
||||
const HEIGHT: u32 = 410;
|
||||
|
||||
fn loading(rgba: Rgba) -> Self {
|
||||
fn loading(rgba: Rgba, now: Instant) -> Self {
|
||||
Self::Loading {
|
||||
blurhash: Blurhash {
|
||||
fade_in: Animation::new(false)
|
||||
.duration(milliseconds(700))
|
||||
.easing(animation::Easing::EaseIn)
|
||||
.go(true),
|
||||
.go(true, now),
|
||||
handle: image::Handle::from_rgba(
|
||||
rgba.width,
|
||||
rgba.height,
|
||||
|
|
@ -309,27 +308,27 @@ impl Preview {
|
|||
}
|
||||
}
|
||||
|
||||
fn ready(rgba: Rgba) -> Self {
|
||||
fn ready(rgba: Rgba, now: Instant) -> Self {
|
||||
Self::Ready {
|
||||
blurhash: None,
|
||||
thumbnail: Thumbnail::new(rgba),
|
||||
thumbnail: Thumbnail::new(rgba, now),
|
||||
}
|
||||
}
|
||||
|
||||
fn load(self, rgba: Rgba) -> Self {
|
||||
fn load(self, rgba: Rgba, now: Instant) -> Self {
|
||||
let Self::Loading { blurhash } = self else {
|
||||
return self;
|
||||
};
|
||||
|
||||
Self::Ready {
|
||||
blurhash: Some(blurhash),
|
||||
thumbnail: Thumbnail::new(rgba),
|
||||
thumbnail: Thumbnail::new(rgba, now),
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_zoom(&mut self, enabled: bool) {
|
||||
fn toggle_zoom(&mut self, enabled: bool, now: Instant) {
|
||||
if let Self::Ready { thumbnail, .. } = self {
|
||||
thumbnail.zoom.go_mut(enabled);
|
||||
thumbnail.zoom.go_mut(enabled, now);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -357,14 +356,14 @@ impl Preview {
|
|||
}
|
||||
|
||||
impl Thumbnail {
|
||||
pub fn new(rgba: Rgba) -> Self {
|
||||
pub fn new(rgba: Rgba, now: Instant) -> Self {
|
||||
Self {
|
||||
handle: image::Handle::from_rgba(
|
||||
rgba.width,
|
||||
rgba.height,
|
||||
rgba.pixels,
|
||||
),
|
||||
fade_in: Animation::new(false).slow().go(true),
|
||||
fade_in: Animation::new(false).slow().go(true, now),
|
||||
zoom: Animation::new(false)
|
||||
.quick()
|
||||
.easing(animation::Easing::EaseInOut),
|
||||
|
|
@ -391,24 +390,24 @@ impl Viewer {
|
|||
}
|
||||
}
|
||||
|
||||
fn open(&mut self) {
|
||||
fn open(&mut self, now: Instant) {
|
||||
self.image = None;
|
||||
self.background_fade_in.go_mut(true);
|
||||
self.background_fade_in.go_mut(true, now);
|
||||
}
|
||||
|
||||
fn show(&mut self, rgba: Rgba) {
|
||||
fn show(&mut self, rgba: Rgba, now: Instant) {
|
||||
self.image = Some(image::Handle::from_rgba(
|
||||
rgba.width,
|
||||
rgba.height,
|
||||
rgba.pixels,
|
||||
));
|
||||
self.background_fade_in.go_mut(true);
|
||||
self.image_fade_in.go_mut(true);
|
||||
self.background_fade_in.go_mut(true, now);
|
||||
self.image_fade_in.go_mut(true, now);
|
||||
}
|
||||
|
||||
fn close(&mut self) {
|
||||
self.background_fade_in.go_mut(false);
|
||||
self.image_fade_in.go_mut(false);
|
||||
fn close(&mut self, now: Instant) {
|
||||
self.background_fade_in.go_mut(false, now);
|
||||
self.image_fade_in.go_mut(false, now);
|
||||
}
|
||||
|
||||
fn is_animating(&self, now: Instant) -> bool {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue