import streamlit as st
import os
import configparser
import glob
import shutil
from datetime import datetime
from pathlib import Path
import re
from utils import parse_winapp2_ini, scan_files, delete_files, get_file_size, format_size
st.set_page_config(
page_title="Windows Data Cleaner",
page_icon="๐งน",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS for better UI
st.markdown("""
""", unsafe_allow_html=True)
# Header with anycoder link
st.markdown('
๐งน Windows Data Cleaner
', unsafe_allow_html=True)
st.markdown('[Built with anycoder](https://huggingface.co/spaces/akhaliq/anycoder)', unsafe_allow_html=True)
st.markdown("---")
# Initialize session state
if 'cleaning_results' not in st.session_state:
st.session_state.cleaning_results = None
if 'scanned_files' not in st.session_state:
st.session_state.scanned_files = []
if 'ini_config' not in st.session_state:
st.session_state.ini_config = None
if 'scan_complete' not in st.session_state:
st.session_state.scan_complete = False
# Sidebar configuration
with st.sidebar:
st.header("โ๏ธ Configuration")
# INI File Upload
st.subheader("WinApp2.ini File")
ini_file = st.file_uploader(
"Upload winapp2.ini",
type=["ini", "txt"],
help="Upload the winapp2.ini configuration file"
)
# Base directory for cleaning
st.subheader("Base Directory")
base_dir = st.text_input(
"Base Directory Path",
value=os.getenv('USERPROFILE', 'C:/Users') or 'C:/Users',
help="Root directory to scan for files"
)
# Cleaning options
st.subheader("Cleaning Options")
dry_run = st.checkbox("Dry Run Mode", value=True, help="Preview files without deleting")
confirm_delete = st.checkbox("Require Confirmation", value=True, help="Ask before deleting files")
# Advanced options
with st.expander("Advanced Options"):
include_hidden = st.checkbox("Include Hidden Files", value=False)
include_system = st.checkbox("Include System Files", value=False, help="Warning: May affect system stability")
max_file_age_days = st.number_input("Max File Age (days)", min_value=0, value=365, help="Only clean files older than this")
# Main content area
st.header("๐ Configuration File")
if ini_file:
try:
# Parse the INI file
with st.spinner("Parsing winapp2.ini..."):
config_content = ini_file.getvalue().decode('utf-8')
st.session_state.ini_config = parse_winapp2_ini(config_content)
if st.session_state.ini_config:
st.success("โ
Configuration file loaded successfully!")
# Display configuration sections
st.subheader("Available Cleaning Sections")
for section_name, section_data in st.session_state.ini_config.items():
with st.expander(f"๐ {section_name}", expanded=False):
st.code(f"Description: {section_data.get('description', 'No description')}")
st.code(f"Warning: {section_data.get('warning', 'No warnings')}")
if 'path' in section_data:
st.code(f"Paths: {section_data['path']}")
if 'file' in section_data:
st.code(f"File Patterns: {section_data['file']}")
if 'regex' in section_data:
st.code(f"Regex Patterns: {section_data['regex']}")
except Exception as e:
st.error(f"โ Error parsing INI file: {str(e)}")
else:
st.info("๐ Please upload a winapp2.ini configuration file to continue.")
st.code("""
# Example winapp2.ini structure
[SectionName]
Description=Description of what this cleans
Warning=Warning message
path=C:\\Users\\*\\AppData\\Local\\Temp
file=*.tmp; *.log
regex=pattern_to_match
""")
# Scan and Preview Section
st.header("๐ Scan & Preview")
if st.session_state.ini_config and base_dir:
if st.button("๐ Scan for Files", type="primary", disabled=not st.session_state.ini_config):
with st.spinner("Scanning directories..."):
try:
scanned_files = scan_files(
st.session_state.ini_config,
base_dir,
include_hidden=include_hidden,
include_system=include_system,
max_age_days=max_file_age_days
)
st.session_state.scanned_files = scanned_files
st.session_state.scan_complete = True
# Calculate totals
total_files = len(scanned_files)
total_size = sum(f['size'] for f in scanned_files)
st.session_state.scan_summary = {
'total_files': total_files,
'total_size': total_size,
'sections': len(st.session_state.ini_config)
}
st.success(f"โ
Scan complete! Found {total_files} files ({format_size(total_size)})")
except Exception as e:
st.error(f"โ Error during scan: {str(e)}")
st.session_state.scan_complete = False
# Display scan results
if st.session_state.scan_complete and st.session_state.scanned_files:
st.subheader("๐ Scan Results")
# Summary statistics
col1, col2, col3 = st.columns(3)
with col1:
st.metric(
label="Total Files",
value=st.session_state.scan_summary['total_files']
)
with col2:
st.metric(
label="Total Size",
value=format_size(st.session_state.scan_summary['total_size'])
)
with col3:
st.metric(
label="Sections",
value=st.session_state.scan_summary['sections']
)
# File list with selection
st.subheader("๐ Files to Clean")
# Create a table of files
if st.session_state.scanned_files:
# Display first 100 files in table
display_files = st.session_state.scanned_files[:100]
file_data = {
'Section': [f['section'] for f in display_files],
'Path': [f['path'] for f in display_files],
'Size': [format_size(f['size']) for f in display_files],
'Age (days)': [f['age_days'] for f in display_files]
}
st.table(file_data)
if len(st.session_state.scanned_files) > 100:
st.info(f"Showing first 100 of {len(st.session_state.scanned_files)} files")
# Download full list
if len(st.session_state.scanned_files) > 0:
import json
file_list_json = json.dumps(st.session_state.scanned_files, indent=2)
st.download_button(
label="๐ฅ Download Full File List",
data=file_list_json,
file_name="scan_results.json",
mime="application/json"
)
# Cleaning Execution Section
st.header("๐งน Execute Cleaning")
if st.session_state.scan_complete and st.session_state.scanned_files:
warning_msg = """
โ ๏ธ WARNING: This operation will delete files from your system.
Please review the file list carefully before proceeding.
Make sure you have backups of important data.
"""
st.markdown(warning_msg, unsafe_allow_html=True)
# Execution controls
col1, col2 = st.columns([3, 1])
with col1:
execute_clean = st.button(
"๐๏ธ Execute Clean Operation",
type="primary",
disabled=dry_run and not st.session_state.scanned_files
)
with col2:
reset_scan = st.button("๐ Reset Scan")
if reset_scan:
st.session_state.scanned_files = []
st.session_state.scan_complete = False
st.session_state.cleaning_results = None
st.rerun()
if execute_clean:
if confirm_delete and not dry_run:
if not st.checkbox("โ
I confirm I want to delete these files"):
st.warning("Please confirm before proceeding")
st.stop()
with st.spinner("Executing clean operation..."):
try:
results = delete_files(
st.session_state.scanned_files,
dry_run=dry_run
)
st.session_state.cleaning_results = results
if dry_run:
success_msg = """
โ
Dry Run Complete: No files were deleted.
This was a preview of what would be cleaned.
"""
else:
success_msg = """
โ
Cleaning Complete: Files have been deleted successfully.
"""
st.markdown(success_msg, unsafe_allow_html=True)
# Display results
if results:
st.subheader("๐ Cleaning Results")
result_col1, result_col2, result_col3 = st.columns(3)
with result_col1:
st.metric("Files Processed", results.get('processed', 0))
with result_col2:
st.metric("Files Deleted", results.get('deleted', 0))
with result_col3:
st.metric("Space Freed", format_size(results.get('size_freed', 0)))
if results.get('errors', []):
st.subheader("โ ๏ธ Errors")
for error in results['errors']:
st.error(error)
except Exception as e:
st.error(f"โ Error during cleaning: {str(e)}")
import traceback
st.code(traceback.format_exc())
# Help and Documentation
st.header("โ Help & Documentation")
with st.expander("How to Use winapp2.ini", expanded=False):
st.markdown("""
**winapp2.ini** is a configuration file format used by cleaning tools like BleachBit.
**Structure:**
```ini
[SectionName]
Description=What this section cleans
Warning=Warning message for users
path=C:\\path\\to\\directory
file=*.ext; *.log
regex=pattern_to_match
**Common Sections:**
- `Temp`: Temporary files
- `Cache`: Browser and application caches
- `Logs`: Application log files
- `Recycle`: Recycle bin contents
""")
with st.expander("Safety Tips", expanded=False):
st.markdown("""
**โ ๏ธ Important Safety Guidelines:**
1. **Always use Dry Run mode first** to preview what will be deleted
2. **Review the file list** before executing deletion
3. **Backup important data** before cleaning
4. **Don't clean system files** unless you know what they do
5. **Start with user data** (Temp, Cache, Logs) before system files
6. **Check application behavior** after cleaning to ensure nothing broke
""")
with st.expander("Troubleshooting", expanded=False):
st.markdown("""
**Common Issues:**
- **Permission Errors**: Run as administrator or check file permissions
- **File Not Found**: Paths may be incorrect or files already deleted
- **INI Parse Errors**: Check INI file format and encoding
- **Slow Scanning**: Large directories or network drives can be slow
** Solutions:**
- Use specific paths instead of wildcards
- Exclude system directories if not needed
- Run in dry run mode first
- Check antivirus software isn't blocking access
""")
# Footer
st.markdown("---")
st.markdown("Made with โค๏ธ using Streamlit | [Built with anycoder](https://huggingface.co/spaces/akhaliq/anycoder)")