ronantakizawa/codereview-bench huggingface dataset:
Repository: alacritty/alacritty
File: alacritty_terminal/src/tty/mod.rs (Rust)

Code before:
#[cfg(windows)]
pub use self::windows::*;

/// Configuration for the `Pty` interface.
#[derive(Clone, PartialEq, Eq, Default)]
pub struct Options {
    /// Shell options.
    ///
    /// [`None`] will use the default shell.
    pub shell: Option<Shell>,

    /// Shell startup directory.
    pub working_directory: Option<PathBuf>,

    /// Drain the child process output before exiting the terminal.
    pub drain_on_exit: bool,

    /// Extra environment variables.
    pub env: HashMap<String, String>,

    /// Specifies whether the shell arguments should be escaped.
    ///
    /// This is useful for passing arguments to applications that don't follow
    /// the standard C run-time escaping rules, such as `cmd.exe /c`.
    #[cfg(target_os = "windows")]
    pub raw_args: bool,
}

/// Shell options.
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct Shell {
    /// Path to a shell program to run on startup.
    pub(crate) program: String,
    /// Arguments passed to shell.
    pub(crate) args: Vec<String>,
}

impl Shell {
    pub fn new(program: String, args: Vec<String>) -> Self {
        Self { program, args }
    }
}

/// Stream read and/or write behavior.
///
/// This defines an abstraction over polling's interface in order to allow either
/// one read/write object or a separate read and write object.
pub trait EventedReadWrite {
    type Reader: io::Read;
    type Writer: io::Write;


Review comment (security):
Maybe it would be a little more clear to turn this around and make it into an `escape_args` boolean, especially since that's going to make Alacritty's default feel more natural.

Code after:
#[cfg(windows)]
pub use self::windows::*;

/// Configuration for the `Pty` interface.
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct Options {
    /// Shell options.
    ///
    /// [`None`] will use the default shell.
    pub shell: Option<Shell>,

    /// Shell startup directory.
    pub working_directory: Option<PathBuf>,

    /// Drain the child process output before exiting the terminal.
    pub drain_on_exit: bool,

    /// Extra environment variables.
    pub env: HashMap<String, String>,

    /// Specifies whether the Windows shell arguments should be escaped.
    ///
    /// - When `true`: Arguments will be escaped according to the standard C runtime rules.
    /// - When `false`: Arguments will be passed raw without additional escaping.
    #[cfg(target_os = "windows")]
    pub escape_args: bool,
}

/// Shell options.
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct Shell {
    /// Path to a shell program to run on startup.
    pub(crate) program: String,
    /// Arguments passed to shell.
    pub(crate) args: Vec<String>,
}

impl Shell {
    pub fn new(program: String, args: Vec<String>) -> Self {
        Self { program, args }
    }
}

/// Stream read and/or write behavior.
///
/// This defines an abstraction over polling's interface in order to allow either
/// one read/write object or a separate read and write object.
pub trait EventedReadWrite {
    type Reader: io::Read;
    type Writer: io::Write;
Repository: alacritty/alacritty
File: alacritty/src/daemon.rs (Rust)

Code before:
        let cwd = std::fs::read_link(link_path)?;

        #[cfg(target_os = "macos")]
        let cwd = macos::proc::cwd(pid)?;

        Ok(cwd)
    }

    #[cfg(target_os = "openbsd")]
    {
        let mut buf = [0u8; libc::PATH_MAX as usize];
        let mut buflen = libc::PATH_MAX as usize;
        if unsafe {
            libc::sysctl(
                [libc::CTL_KERN, libc::KERN_PROC_CWD, pid].as_ptr(),
                3,
                buf.as_mut_ptr() as *mut _,
                &mut buflen as *mut _,
                std::ptr::null_mut(),
                0,
            )
        } != 0
        {
            return Err("Could not read cwd".into());
        }
        let s = unsafe { std::ffi::CStr::from_ptr(buf.as_ptr() as *const _) }.to_str()?;
        Ok(PathBuf::from(s))
    }
}


Review comment (suggestion):
`Cstr` should be importade at the top. Additionally `s` is a terrible variable name. I recommend going with something like `foreground_path` instead.

Also I *think* `buf.as_ptr().cast()` should work here? It's a little more idiomatic I believe.

Code after:
    #[cfg(target_os = "freebsd")]
    let link_path = format!("/compat/linux/proc/{}/cwd", pid);

    #[cfg(not(target_os = "macos"))]
    let cwd = fs::read_link(link_path)?;

    #[cfg(target_os = "macos")]
    let cwd = macos::proc::cwd(pid)?;

    Ok(cwd)
}

#[cfg(target_os = "openbsd")]
pub fn foreground_process_path(
    master_fd: RawFd,
    shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
    let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
    if pid < 0 {
        pid = shell_pid as pid_t;
    }
    let name = [libc::CTL_KERN, libc::KERN_PROC_CWD, pid];
    let mut buf = [0u8; libc::PATH_MAX as usize];
    let result = unsafe {
        libc::sysctl(
            name.as_ptr(),
            name.len().try_into().unwrap(),
            buf.as_mut_ptr() as *mut _,
            &mut buf.len() as *mut _,
            ptr::null_mut(),
            0,
        )
    };
    if result != 0 {
        Err(io::Error::last_os_error().into())
    } else {
        let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }.to_str()?;
        Ok(PathBuf::from(foreground_path))
    }
}
Repository: alacritty/alacritty
File: alacritty/src/daemon.rs (Rust)

Code before:
    #[cfg(not(target_os = "macos"))]
    let cwd = fs::read_link(link_path)?;

    #[cfg(target_os = "macos")]
    let cwd = macos::proc::cwd(pid)?;

    Ok(cwd)
}

#[cfg(target_os = "openbsd")]
pub fn foreground_process_path(
    master_fd: RawFd,
    shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
    let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
    if pid < 0 {
        pid = shell_pid as pid_t;
    }
    let mut buf = [0u8; libc::PATH_MAX as usize];
    let mut buflen = libc::PATH_MAX as usize;
    let result = unsafe {
        libc::sysctl(
            [libc::CTL_KERN, libc::KERN_PROC_CWD, pid].as_ptr(),
            3,
            buf.as_mut_ptr() as *mut _,
            &mut buflen as *mut _,
            ptr::null_mut(),
            0,
        )
    };
    if result != 0 {
        return Err(io::Error::last_os_error().into());
    }
    let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr() as *const _) }.to_str()?;
    Ok(PathBuf::from(foreground_path))
}


Review comment (suggestion):
Wouldn't something like that work? In general, `len` should always be taken from the buffer, so it's less error prone.

```suggestion
            &mut buf.len() as *mut _,
```

Code after:

    #[cfg(not(target_os = "macos"))]
    let cwd = fs::read_link(link_path)?;

    #[cfg(target_os = "macos")]
    let cwd = macos::proc::cwd(pid)?;

    Ok(cwd)
}

#[cfg(target_os = "openbsd")]
pub fn foreground_process_path(
    master_fd: RawFd,
    shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
    let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
    if pid < 0 {
        pid = shell_pid as pid_t;
    }
    let name = [libc::CTL_KERN, libc::KERN_PROC_CWD, pid];
    let mut buf = [0u8; libc::PATH_MAX as usize];
    let result = unsafe {
        libc::sysctl(
            name.as_ptr(),
            name.len().try_into().unwrap(),
            buf.as_mut_ptr() as *mut _,
            &mut buf.len() as *mut _,
            ptr::null_mut(),
            0,
        )
    };
    if result != 0 {
        Err(io::Error::last_os_error().into())
    } else {
        let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }.to_str()?;
        Ok(PathBuf::from(foreground_path))
    }
}
Repository: alacritty/alacritty
File: alacritty/src/daemon.rs (Rust)

Code before:
    let link_path = format!("/compat/linux/proc/{}/cwd", pid);

    #[cfg(not(target_os = "macos"))]
    let cwd = fs::read_link(link_path)?;

    #[cfg(target_os = "macos")]
    let cwd = macos::proc::cwd(pid)?;

    Ok(cwd)
}

#[cfg(target_os = "openbsd")]
pub fn foreground_process_path(
    master_fd: RawFd,
    shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
    let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
    if pid < 0 {
        pid = shell_pid as pid_t;
    }
    let mut buf = [0u8; libc::PATH_MAX as usize];
    let mut buflen = libc::PATH_MAX as usize;
    let result = unsafe {
        libc::sysctl(
            [libc::CTL_KERN, libc::KERN_PROC_CWD, pid].as_ptr(),
            3,
            buf.as_mut_ptr() as *mut _,
            &mut buflen as *mut _,
            ptr::null_mut(),
            0,
        )
    };
    if result != 0 {
        return Err(io::Error::last_os_error().into());
    }
    let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr() as *const _) }.to_str()?;
    Ok(PathBuf::from(foreground_path))
}


Review comment (suggestion):
This array should be bound and then `3` taken from `len()`.

Code after:
    #[cfg(target_os = "freebsd")]
    let link_path = format!("/compat/linux/proc/{}/cwd", pid);

    #[cfg(not(target_os = "macos"))]
    let cwd = fs::read_link(link_path)?;

    #[cfg(target_os = "macos")]
    let cwd = macos::proc::cwd(pid)?;

    Ok(cwd)
}

#[cfg(target_os = "openbsd")]
pub fn foreground_process_path(
    master_fd: RawFd,
    shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
    let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
    if pid < 0 {
        pid = shell_pid as pid_t;
    }
    let name = [libc::CTL_KERN, libc::KERN_PROC_CWD, pid];
    let mut buf = [0u8; libc::PATH_MAX as usize];
    let result = unsafe {
        libc::sysctl(
            name.as_ptr(),
            name.len().try_into().unwrap(),
            buf.as_mut_ptr() as *mut _,
            &mut buf.len() as *mut _,
            ptr::null_mut(),
            0,
        )
    };
    if result != 0 {
        Err(io::Error::last_os_error().into())
    } else {
        let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }.to_str()?;
        Ok(PathBuf::from(foreground_path))
    }
}
Repository: alacritty/alacritty
File: alacritty/src/daemon.rs (Rust)

Code before:
    }

    #[cfg(not(any(target_os = "macos", target_os = "freebsd")))]
    let link_path = format!("/proc/{pid}/cwd");
    #[cfg(target_os = "freebsd")]
    let link_path = format!("/compat/linux/proc/{}/cwd", pid);

    #[cfg(not(target_os = "macos"))]
    let cwd = fs::read_link(link_path)?;

    #[cfg(target_os = "macos")]
    let cwd = macos::proc::cwd(pid)?;

    Ok(cwd)
}

#[cfg(target_os = "openbsd")]
pub fn foreground_process_path(
    master_fd: RawFd,
    shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
    let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
    if pid < 0 {
        pid = shell_pid as pid_t;
    }
    let name = [libc::CTL_KERN, libc::KERN_PROC_CWD, pid];
    let mut buf = [0u8; libc::PATH_MAX as usize];
    let result = unsafe {
        libc::sysctl(
            name.as_ptr(),
            name.len().try_into().unwrap(),
            buf.as_mut_ptr() as *mut _,
            &mut buf.len() as *mut _,
            ptr::null_mut(),
            0,
        )
    };
    if result != 0 {
        return Err(io::Error::last_os_error().into());
    }
    let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }.to_str()?;
    Ok(PathBuf::from(foreground_path))
}


Review comment (suggestion):
This might be more than it's worth, but we should consider making the PID code it's own shared function since it's the same between the implementations.

Code after:
        pid = shell_pid as pid_t;
    }

    #[cfg(not(any(target_os = "macos", target_os = "freebsd")))]
    let link_path = format!("/proc/{pid}/cwd");
    #[cfg(target_os = "freebsd")]
    let link_path = format!("/compat/linux/proc/{}/cwd", pid);

    #[cfg(not(target_os = "macos"))]
    let cwd = fs::read_link(link_path)?;

    #[cfg(target_os = "macos")]
    let cwd = macos::proc::cwd(pid)?;

    Ok(cwd)
}

#[cfg(target_os = "openbsd")]
pub fn foreground_process_path(
    master_fd: RawFd,
    shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
    let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
    if pid < 0 {
        pid = shell_pid as pid_t;
    }
    let name = [libc::CTL_KERN, libc::KERN_PROC_CWD, pid];
    let mut buf = [0u8; libc::PATH_MAX as usize];
    let result = unsafe {
        libc::sysctl(
            name.as_ptr(),
            name.len().try_into().unwrap(),
            buf.as_mut_ptr() as *mut _,
            &mut buf.len() as *mut _,
            ptr::null_mut(),
            0,
        )
    };
    if result != 0 {
        Err(io::Error::last_os_error().into())
    } else {
        let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }.to_str()?;
        Ok(PathBuf::from(foreground_path))
    }
}
Repository: alacritty/alacritty
File: alacritty/src/daemon.rs (Rust)

Code before:
#[cfg(target_os = "openbsd")]
pub fn foreground_process_path(
    master_fd: RawFd,
    shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
    let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
    if pid < 0 {
        pid = shell_pid as pid_t;
    }
    let name = [libc::CTL_KERN, libc::KERN_PROC_CWD, pid];
    let mut buf = [0u8; libc::PATH_MAX as usize];
    let result = unsafe {
        libc::sysctl(
            name.as_ptr(),
            name.len().try_into().unwrap(),
            buf.as_mut_ptr() as *mut _,
            &mut buf.len() as *mut _,
            ptr::null_mut(),
            0,
        )
    };
    if result != 0 {
        return Err(io::Error::last_os_error().into());
    }
    let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }.to_str()?;
    Ok(PathBuf::from(foreground_path))
}


Review comment (suggestion):
```suggestion
    if result != 0 {
        Err(io::Error::last_os_error().into())
    } else {
        let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }.to_str()?;
        Ok(PathBuf::from(foreground_path))
    }
```

Should do it either this way or add a newline between the early return and the successful return.

Code after:

#[cfg(target_os = "openbsd")]
pub fn foreground_process_path(
    master_fd: RawFd,
    shell_pid: u32,
) -> Result<PathBuf, Box<dyn Error>> {
    let mut pid = unsafe { libc::tcgetpgrp(master_fd) };
    if pid < 0 {
        pid = shell_pid as pid_t;
    }
    let name = [libc::CTL_KERN, libc::KERN_PROC_CWD, pid];
    let mut buf = [0u8; libc::PATH_MAX as usize];
    let result = unsafe {
        libc::sysctl(
            name.as_ptr(),
            name.len().try_into().unwrap(),
            buf.as_mut_ptr() as *mut _,
            &mut buf.len() as *mut _,
            ptr::null_mut(),
            0,
        )
    };
    if result != 0 {
        Err(io::Error::last_os_error().into())
    } else {
        let foreground_path = unsafe { CStr::from_ptr(buf.as_ptr().cast()) }.to_str()?;
        Ok(PathBuf::from(foreground_path))
    }
}
Repository: alacritty/alacritty
File: alacritty/src/daemon.rs (Rust)

Code before:
use std::ffi::OsStr;
#[cfg(not(any(target_os = "macos", target_os = "openbsd", windows)))]
use std::fs;
use std::io;
#[cfg(windows)]
use std::os::windows::process::CommandExt;
use std::process::{Command, Stdio};

#[rustfmt::skip]
#[cfg(not(windows))]
use {
    std::env,
    std::error::Error,
    std::os::unix::process::CommandExt,
    std::os::unix::io::RawFd,
    std::path::PathBuf,
};

#[cfg(not(windows))]
use libc::pid_t;
#[cfg(windows)]
use windows_sys::Win32::System::Threading::{CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW};

#[cfg(target_os = "openbsd")]
use std::{ffi::CStr, ptr};

#[cfg(target_os = "macos")]
use crate::macos;

/// Start a new process in the background.
#[cfg(windows)]
pub fn spawn_daemon<I, S>(program: &str, args: I) -> io::Result<()>
where
    I: IntoIterator<Item = S> + Copy,
    S: AsRef<OsStr>,
{
    // Setting all the I/O handles to null and setting the
    // CREATE_NEW_PROCESS_GROUP and CREATE_NO_WINDOW has the effect
    // that console applications will run without opening a new
    // console window.
    Command::new(program)
        .args(args)
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .creation_flags(CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW)
        .spawn()
        .map(|_| ())
}


Review comment (suggestion):
I thought rustfmt should error on this, I guess it doesn't because there's a cfg attr?

These should be two separate lines. It's a bit unfortunate because that requires duplicating the cfg attr, but it's necessary for consistency with the rest of the imports. Ideally rustfmt should do this automatically…

Code after:
#[cfg(target_os = "openbsd")]
use std::ffi::CStr;
use std::ffi::OsStr;
#[cfg(not(any(target_os = "macos", target_os = "openbsd", windows)))]
use std::fs;
use std::io;
#[cfg(windows)]
use std::os::windows::process::CommandExt;
use std::process::{Command, Stdio};
#[cfg(target_os = "openbsd")]
use std::ptr;

#[rustfmt::skip]
#[cfg(not(windows))]
use {
    std::env,
    std::error::Error,
    std::os::unix::process::CommandExt,
    std::os::unix::io::RawFd,
    std::path::PathBuf,
};

#[cfg(not(windows))]
use libc::pid_t;
#[cfg(windows)]
use windows_sys::Win32::System::Threading::{CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW};

#[cfg(target_os = "macos")]
use crate::macos;

/// Start a new process in the background.
#[cfg(windows)]
pub fn spawn_daemon<I, S>(program: &str, args: I) -> io::Result<()>
where
    I: IntoIterator<Item = S> + Copy,
    S: AsRef<OsStr>,
{
    // Setting all the I/O handles to null and setting the
    // CREATE_NEW_PROCESS_GROUP and CREATE_NO_WINDOW has the effect
    // that console applications will run without opening a new
    // console window.
    Command::new(program)
        .args(args)
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .creation_flags(CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW)
        .spawn()
        .map(|_| ())
}
Repository: alievk/avatarify
File: run.sh (Shell)

Code before:
        fi
    fi

    if [[ $DOCKER_IS_LOCAL_CLIENT == 1 ]]; then
        DOCKER_ARGS="$DOCKER_ARGS --network=host"
    elif [[ $IS_CLIENT == 1 ]]; then
        DOCKER_ARGS="$DOCKER_ARGS -p 5557:5554 -p 5557:5558"
    fi


    if [[ $IS_WORKER == 0 ]]; then
        xhost +local:root
        docker run $DOCKER_ARGS -it --rm --privileged  \
            -v $PWD:/root/.torch/models \
            -v $PWD/avatars:/app/avatarify/avatars \
            --env="DISPLAY" \
            --env="QT_X11_NO_MITSHM=1" \
            --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
            avatarify python3 afy/cam_fomm.py \
                --config $FOMM_CONFIG \
                --checkpoint $FOMM_CKPT \
                --virt-cam $CAMID_VIRT \
                --relative \
                --adapt_scale \
                $@ \
        && $(DOCKER_DEPRECATION_WARNING)
        xhost -local:root

    else
        docker run $DOCKER_ARGS -it --rm --privileged  \
            -v $PWD:/root/.torch/models \
            -v $PWD/avatars:/app/avatarify/avatars \
            avatarify python3 afy/cam_fomm.py \
                --config $FOMM_CONFIG \
                --checkpoint $FOMM_CKPT \
                --virt-cam $CAMID_VIRT \
                --relative \
                --adapt_scale \
                $@ \
        && $(DOCKER_DEPRECATION_WARNING)
    fi

fi


Review comment (suggestion):
The error @alievk mentioned comes from here, `$DOCKER_DEPRECATION_WARNING` should be the right syntax. 
Imho it'd be cleaner to directly echo in line 109.

Code after:
    fi

    if [[ $DOCKER_IS_LOCAL_CLIENT == 1 ]]; then
        DOCKER_ARGS="$DOCKER_ARGS --network=host"
    elif [[ $IS_CLIENT == 1 ]]; then
        DOCKER_ARGS="$DOCKER_ARGS -p 5557:5554 -p 5557:5558"
    fi


    if [[ $IS_WORKER == 0 ]]; then
        xhost +local:root
        docker run $DOCKER_ARGS -it --rm --privileged  \
            -v $PWD:/root/.torch/models \
            -v $PWD/avatars:/app/avatarify/avatars \
            --env="DISPLAY" \
            --env="QT_X11_NO_MITSHM=1" \
            --volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
            avatarify python3 afy/cam_fomm.py \
                --config $FOMM_CONFIG \
                --checkpoint $FOMM_CKPT \
                --virt-cam $CAMID_VIRT \
                --relative \
                --adapt_scale \
                $@
        xhost -local:root

    else
        docker run $DOCKER_ARGS -it --rm --privileged  \
            -v $PWD:/root/.torch/models \
            -v $PWD/avatars:/app/avatarify/avatars \
            avatarify python3 afy/cam_fomm.py \
                --config $FOMM_CONFIG \
                --checkpoint $FOMM_CKPT \
                --virt-cam $CAMID_VIRT \
                --relative \
                --adapt_scale \
                $@
    fi

fi
Repository: android/compose-samples
File: Crane/app/src/main/java/androidx/compose/samples/crane/home/LandingScreen.kt (Kotlin)

Code before:
 */

package androidx.compose.samples.crane.home

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.samples.crane.R
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.vectorResource
import kotlinx.coroutines.delay

private const val SplashWaitTime: Long = 2000

@Composable
fun LandingScreen(modifier: Modifier = Modifier, onTimeout: () -> Unit) {
    Box(modifier = modifier.fillMaxSize(), alignment = Alignment.Center) {
        LaunchedEffect(Unit) {
            delay(SplashWaitTime)
            onTimeout()
        }
        Image(asset = vectorResource(id = R.drawable.ic_crane_drawer))
    }
}


Review comment (suggestion):
This will call the `onTimeout` from initial composition even if it changes.

Suggested changes: Either pass onTimeout to LaunchedEffect to restart the timer, or use `rememberUpdatedState` to safely capture `onTimeout`

Code after:
 */

package androidx.compose.samples.crane.home

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.samples.crane.R
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.vectorResource
import kotlinx.coroutines.delay

private const val SplashWaitTime: Long = 2000

@Composable
fun LandingScreen(modifier: Modifier = Modifier, onTimeout: () -> Unit) {
    Box(modifier = modifier.fillMaxSize(), alignment = Alignment.Center) {
        // Adds composition consistency. Use the value when LaunchedEffect is first called
        val currentOnTimeout by rememberUpdatedState(onTimeout)

        LaunchedEffect(Unit) {
            delay(SplashWaitTime)
            currentOnTimeout()
        }
        Image(asset = vectorResource(id = R.drawable.ic_crane_drawer))
    }
}