1 Commits

Author SHA1 Message Date
Mukhtar Akere
742d8fb088 - Fix issues with cache dir
Some checks failed
GoReleaser / goreleaser (push) Has been cancelled
Release Docker Build / docker (push) Has been cancelled
- Fix responsiveness issue with navbars
- Support user entry for users running as non-root
- Other minor fixes
2025-08-12 15:14:42 +01:00
10 changed files with 132 additions and 29 deletions

View File

@@ -52,10 +52,6 @@ func (m *Manager) mountWithRetry(provider, webdavURL string, maxRetries int) err
func (m *Manager) performMount(provider, webdavURL string) error {
cfg := config.Get()
mountPath := filepath.Join(cfg.Rclone.MountPath, provider)
cacheDir := ""
if cfg.Rclone.CacheDir != "" {
cacheDir = filepath.Join(cfg.Rclone.CacheDir, provider)
}
// Create mount directory
if err := os.MkdirAll(mountPath, 0755); err != nil {
@@ -78,14 +74,13 @@ func (m *Manager) performMount(provider, webdavURL string) error {
}
// Create rclone config for this provider
configName := fmt.Sprintf("decypharr-%s", provider)
if err := m.createConfig(configName, webdavURL); err != nil {
if err := m.createConfig(provider, webdavURL); err != nil {
return fmt.Errorf("failed to create rclone config: %w", err)
}
// Prepare mount arguments
mountArgs := map[string]interface{}{
"fs": fmt.Sprintf("%s:", configName),
"fs": fmt.Sprintf("%s:", provider),
"mountPoint": mountPath,
"mountType": "mount", // Use standard FUSE mount
"mountOpt": map[string]interface{}{
@@ -103,15 +98,6 @@ func (m *Manager) performMount(provider, webdavURL string) error {
configOpts["BufferSize"] = cfg.Rclone.BufferSize
}
if cacheDir != "" {
// Create cache directory if specified
if err := os.MkdirAll(cacheDir, 0755); err != nil {
m.logger.Warn().Str("cacheDir", cacheDir).Msg("Failed to create cache directory")
} else {
configOpts["CacheDir"] = cacheDir
}
}
if len(configOpts) > 0 {
// Only add _config if there are options to set
mountArgs["_config"] = configOpts
@@ -180,7 +166,7 @@ func (m *Manager) performMount(provider, webdavURL string) error {
WebDAVURL: webdavURL,
Mounted: true,
MountedAt: time.Now().Format(time.RFC3339),
ConfigName: configName,
ConfigName: provider,
}
m.mountsMutex.Lock()
@@ -319,7 +305,7 @@ func (m *Manager) RefreshDir(provider string, dirs []string) error {
dirs = []string{"/"}
}
args := map[string]interface{}{
"fs": fmt.Sprintf("decypharr-%s:", provider),
"fs": fmt.Sprintf("%s:", provider),
}
for i, dir := range dirs {
if dir != "" {

View File

@@ -44,7 +44,7 @@ func (m *Manager) checkMountHealth(provider string) bool {
req := RCRequest{
Command: "operations/list",
Args: map[string]interface{}{
"fs": fmt.Sprintf("decypharr-%s:", provider),
"fs": fmt.Sprintf("%s:", provider),
"remote": "/",
},
}

View File

@@ -105,6 +105,11 @@ func (m *Manager) Start(ctx context.Context) error {
"--config", filepath.Join(m.configDir, "rclone.conf"),
"--log-level", "INFO",
}
if cfg.Rclone.CacheDir != "" {
if err := os.MkdirAll(cfg.Rclone.CacheDir, 0755); err == nil {
args = append(args, "--cache-dir", cfg.Rclone.CacheDir)
}
}
m.cmd = exec.CommandContext(ctx, "rclone", args...)
m.cmd.Dir = m.configDir

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -414,8 +414,91 @@ class DecypharrUtils {
}
}
// Mobile navigation dropdown handler
setupMobileNavigation() {
const mobileMenuBtn = document.querySelector('.navbar-start .dropdown [role="button"]');
const mobileMenu = document.querySelector('.navbar-start .dropdown .dropdown-content');
const dropdown = document.querySelector('.navbar-start .dropdown');
if (!mobileMenuBtn || !mobileMenu || !dropdown) return;
let isOpen = false;
const openDropdown = () => {
if (!isOpen) {
dropdown.classList.add('dropdown-open');
mobileMenuBtn.setAttribute('aria-expanded', 'true');
isOpen = true;
}
};
const closeDropdown = () => {
if (isOpen) {
dropdown.classList.remove('dropdown-open');
mobileMenuBtn.setAttribute('aria-expanded', 'false');
isOpen = false;
}
};
const toggleDropdown = (e) => {
e.preventDefault();
e.stopPropagation();
if (isOpen) {
closeDropdown();
} else {
openDropdown();
}
};
// Handle button clicks (both mouse and touch)
mobileMenuBtn.addEventListener('click', toggleDropdown);
mobileMenuBtn.addEventListener('touchend', (e) => {
e.preventDefault();
toggleDropdown(e);
});
// Close dropdown when clicking outside
document.addEventListener('click', (e) => {
if (isOpen && !dropdown.contains(e.target)) {
closeDropdown();
}
});
// Close dropdown when touching outside
document.addEventListener('touchend', (e) => {
if (isOpen && !dropdown.contains(e.target)) {
closeDropdown();
}
});
// Close dropdown when clicking menu items
mobileMenu.addEventListener('click', (e) => {
if (e.target.tagName === 'A') {
closeDropdown();
}
});
// Handle keyboard navigation
mobileMenuBtn.addEventListener('keydown', (e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
toggleDropdown(e);
} else if (e.key === 'Escape') {
closeDropdown();
}
});
// Set initial aria attributes
mobileMenuBtn.setAttribute('aria-expanded', 'false');
mobileMenuBtn.setAttribute('aria-haspopup', 'true');
}
// Global event listeners
setupGlobalEventListeners() {
// Setup mobile navigation dropdown
this.setupMobileNavigation();
// Smooth scroll for anchor links
document.addEventListener('click', (e) => {
const link = e.target.closest('a[href^="#"]');

View File

@@ -487,7 +487,7 @@
</div>
<div class="form-control">
<label class="label" for="rclone.umask">
<span class="label-text font-medium">Group ID (PGID)</span>
<span class="label-text font-medium">UMASK</span>
</label>
<input type="text" class="input input-bordered" name="rclone.umask" id="rclone.umask" placeholder="0022">
<div class="label">

View File

@@ -60,9 +60,6 @@
<li><a href="{{.URLBase}}webdav" target="_blank">
<i class="bi bi-cloud text-success"></i>WebDAV
</a></li>
<li><a href="{{.URLBase}}stats" class="{{if eq .Page "stats"}}active{{end}}">
<i class="bi bi-graph-up text-info"></i>Stats
</a></li>
<li><a href="{{.URLBase}}logs" target="_blank">
<i class="bi bi-journal-text text-warning"></i>Logs
</a></li>

View File

@@ -180,8 +180,8 @@
</div>
<div class="stat">
<div class="stat-title">Elapsed Time</div>
<div class="stat-value text-accent">${((cs.elapsedTime || 0) / 60).toFixed(1)}m</div>
<div class="stat-desc">Transfer: ${((cs.transferTime || 0) / 60).toFixed(1)}m</div>
<div class="stat-value text-accent">${window.decypharrUtils.formatDuration(cs.elapsedTime)}</div>
<div class="stat-desc">Transfer: ${window.decypharrUtils.formatDuration(cs.transferTime)}m</div>
</div>
`;
}
@@ -225,7 +225,7 @@
</div>
<div class="flex justify-between text-xs text-base-content/60 mt-1">
<span>${window.decypharrUtils.formatBytes(transfer.bytes || 0)} / ${window.decypharrUtils.formatBytes(transfer.size || 0)}</span>
<span>ETA: ${transfer.eta ? Math.ceil(transfer.eta / 60) + 'm' : 'Unknown'}</span>
<span>ETA: ${transfer.eta ? window.decypharrUtils.formatDuration(transfer.eta) : 'Unknown'}</span>
</div>
</div>
</div>

View File

@@ -4,6 +4,38 @@ set -e
# Default values
PUID=${PUID:-1000}
PGID=${PGID:-1000}
UMASK=${UMASK:-022}
# Set umask
umask "$UMASK"
# Function to create directories and files
setup_directories() {
# Ensure directories exist
mkdir -p /app/logs /app/cache 2>/dev/null || true
# Create log file if it doesn't exist
touch /app/logs/decypharr.log 2>/dev/null || true
# Try to set permissions if possible
chmod 755 /app 2>/dev/null || true
chmod 666 /app/logs/decypharr.log 2>/dev/null || true
}
# Check if we're running as root
if [ "$(id -u)" != "0" ]; then
echo "Running as non-root user $(id -u):$(id -g) with umask $UMASK"
# Try to create directories as the current user
setup_directories
export USER="$(id -un)"
export HOME="/app"
exec "$@"
fi
echo "Running as root, setting up user $PUID:$PGID with umask $UMASK"
# Create group if it doesn't exist
if ! getent group "$PGID" > /dev/null 2>&1; then
@@ -19,7 +51,7 @@ fi
USERNAME=$(getent passwd "$PUID" | cut -d: -f1)
GROUPNAME=$(getent group "$PGID" | cut -d: -f1)
# Ensure directories exist and have correct permissions
# Create directories and set proper ownership
mkdir -p /app/logs /app/cache
chown -R "$PUID:$PGID" /app
chmod 755 /app