File size: 3,392 Bytes
4b1d79b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
"""Local file browser rendered inside Streamlit, without desktop GUI calls."""
from pathlib import Path

import streamlit as st
from app_environment import hosted_mode


def close_picker():
    st.session_state.picker_open = False


def set_directory(path):
    target = Path(path).expanduser()
    try:
        if not target.is_dir():
            raise ValueError('Folder not found or not accessible.')
        st.session_state.picker_directory = str(target.resolve())
        st.session_state.picker_address = str(target.resolve())
        st.session_state.pop('picker_error', None)
    except (OSError, ValueError) as e:
        st.session_state.picker_error = str(e)


def navigate_address():
    set_directory(st.session_state.picker_address.strip().strip('"'))


def choose_file(path):
    st.session_state.pending_model = str(path.resolve())
    close_picker()


def file_size(size):
    return f'{size / 1024**3:.2f} GB' if size >= 1024**3 else f'{size / 1024**2:.1f} MB'


@st.dialog('Open model', width='large', on_dismiss=close_picker)
def show_model_picker():
    if hosted_mode():
        st.error('Server filesystem browsing is disabled in the hosted app. Use uploads or Hugging Face instead.')
        return
    current = Path(st.session_state.get('picker_directory', str(Path.cwd())))
    if 'picker_address' not in st.session_state:
        st.session_state.picker_address = str(current)
    up, address = st.columns([1, 8], vertical_alignment='bottom')
    up.button('↑ Up', disabled=current == current.parent, on_click=set_directory,
              args=(current.parent,), use_container_width=True)
    address.text_input('Folder path', key='picker_address', on_change=navigate_address,
                       placeholder='Paste a folder path and press Enter')
    current = Path(st.session_state.get('picker_directory', str(Path.cwd())))
    if 'picker_error' in st.session_state:
        st.error(st.session_state.picker_error)
    st.caption(f'Showing: {current}')
    try:
        entries = sorted(current.iterdir(), key=lambda p: p.name.lower())
        folders = [p for p in entries if p.is_dir() and not p.name.startswith('.')]
        files = [p for p in entries if p.is_file() and p.suffix.lower() in {'.gguf', '.safetensors'}]
    except OSError as e:
        st.error(f'Could not read this folder: {e}')
        return
    with st.container(height=300, border=True):
        for folder in folders:
            st.button(f'📁 {folder.name}', key=f'folder:{folder}', on_click=set_directory,
                      args=(folder,), use_container_width=True)
        for file in files:
            label, size = st.columns([5, 1], vertical_alignment='center')
            if label.button(f'📄 {file.name}', key=f'file:{file}', use_container_width=True):
                choose_file(file)
                st.rerun()
            try:
                size.caption(file_size(file.stat().st_size))
            except OSError:
                size.caption('Unavailable')
        if not files:
            st.info('No GGUF or safetensors files here. Open a subfolder or enter another path above.')
    count, cancel = st.columns([5, 1], vertical_alignment='center')
    count.caption(f'{len(folders)} folders · {len(files)} model files · Click a model to select it')
    if cancel.button('Cancel', use_container_width=True):
        close_picker()
        st.rerun()