Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/src/components/common/Icon.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ defineProps<{ name: string; size?: number }>()
</template>
<template v-else-if="name === 'settings'">
<circle cx="12" cy="12" r="3" />
<path d="M12 3l1.76 2.34 2.9-.4 1.03 2.9 2.9 1.03-.4 2.9 1.76 1.76-2.34 1.76.4 2.9-2.9 1.03-1.03 2.9-2.9-.4L12 21l-1.76-2.34-2.9.4-1.03-2.9-2.9-1.03.4-2.9L3 10.57l2.34-1.76-.4-2.9 2.9-1.03 1.03-2.9 2.9.4z" />
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.38a2 2 0 0 0-.73-2.73l-.15-.09a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z" />
</template>
<template v-else-if="name === 'history'">
<path d="M3 3v5h5" /><path d="M3.05 13A9 9 0 1 0 6 5.3L3 8" /><path d="M12 7v5l4 2" />
Expand Down
66 changes: 35 additions & 31 deletions internal/light/filetransfer.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"net"
Expand Down Expand Up @@ -37,27 +38,27 @@ type sendControl struct {
// FileTransferService runs a per-device HTTP server that receives files and
// drives outgoing uploads to peers.
type FileTransferService struct {
app *application.App
manager *TransferManager
settings *SettingsService
app *application.App
manager *TransferManager
settings *SettingsService
discovery *DiscoveryService

mu sync.Mutex
server *http.Server
ln net.Listener
mux *http.ServeMux
accepts map[string]*acceptState
mu sync.Mutex
server *http.Server
ln net.Listener
mux *http.ServeMux
accepts map[string]*acceptState
controls map[string]*sendControl
}

func NewFileTransferService(app *application.App, manager *TransferManager, settings *SettingsService, discovery *DiscoveryService) *FileTransferService {
return &FileTransferService{
app: app,
manager: manager,
settings: settings,
app: app,
manager: manager,
settings: settings,
discovery: discovery,
accepts: make(map[string]*acceptState),
controls: make(map[string]*sendControl),
accepts: make(map[string]*acceptState),
controls: make(map[string]*sendControl),
}
}

Expand Down Expand Up @@ -191,9 +192,9 @@ func (s *FileTransferService) handleTransfer(w http.ResponseWriter, r *http.Requ
return
}

dl := s.receiveDir()
if mkErr := os.MkdirAll(dl, 0o755); mkErr != nil {
http.Error(w, "cannot create destination dir: "+mkErr.Error(), 500)
dl, err := s.receiveDir()
if err != nil {
http.Error(w, "cannot create destination dir: "+err.Error(), 500)
return
}
path := uniquePath(filepath.Join(dl, sanitize(fname)))
Expand Down Expand Up @@ -273,23 +274,26 @@ func (s *FileTransferService) handleTransfer(w http.ResponseWriter, r *http.Requ
// receiveDir returns the directory the receiver writes incoming files to. On
// mobile the chosen SAF folder is not raw-filesystem-writable under scoped
// storage, so we stage into an app-internal dir; desktop honours DownloadDir.
func (s *FileTransferService) receiveDir() string {
func (s *FileTransferService) receiveDir() (string, error) {
if PlatformDeviceType() == DeviceTypeMobile {
dir := filepath.Join(configDir(), "downloads")
if mkErr := os.MkdirAll(dir, 0o755); mkErr == nil {
return dir
}
// Fallback 1: temp dir
dir = filepath.Join(os.TempDir(), "light-downloads")
if mkErr := os.MkdirAll(dir, 0o755); mkErr == nil {
return dir
var lastErr error
for _, dir := range []string{
filepath.Join(configDir(), "downloads"),
filepath.Join(os.TempDir(), "light-downloads"),
} {
if mkErr := os.MkdirAll(dir, 0o755); mkErr == nil {
return dir, nil
} else {
lastErr = mkErr
}
}
// Fallback 2: current working directory
dir = filepath.Join(".", "light-downloads")
_ = os.MkdirAll(dir, 0o755)
return dir
return "", fmt.Errorf("no writable staging directory: %w", lastErr)
}
dir := s.settings.GetSettings().DownloadDir
if err := os.MkdirAll(dir, 0o755); err != nil {
return "", err
}
return s.settings.GetSettings().DownloadDir
return dir, nil
}

// ---- Sender side ----
Expand Down Expand Up @@ -433,7 +437,7 @@ func (s *FileTransferService) upload(tid, peerAddr, filePath, fname string, size
if resp.StatusCode != 200 {
errMsg := fmt.Sprintf("receiver error %d: %s", resp.StatusCode, strings.TrimSpace(string(respBody)))
s.failTransfer(subID, fname, errMsg)
return fmt.Errorf(errMsg)
return errors.New(errMsg)
}

s.manager.Complete(subID, "", sum)
Expand Down
16 changes: 9 additions & 7 deletions internal/light/settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func configDir() string {
func androidInternalDir() string {
// Android app internal storage: /data/data/<pkg>/files or /data/user/0/<pkg>/files
// We try known package names and both data roots.
packages := []string{"com.wails.app", "com.wails.app.light", "com.wails.app.debug"}
packages := []string{"com.light.fileshare", "com.wails.app", "com.wails.app.light", "com.wails.app.debug"}
roots := []string{"/data/data", "/data/user/0"}
// Also try ANDROID_DATA env if set
if ad := os.Getenv("ANDROID_DATA"); ad != "" && ad != "/" {
Expand Down Expand Up @@ -160,12 +160,14 @@ func (s *SettingsService) UpdateSettings(s2 Settings) {
s.emit()
}

func (s *SettingsService) SetDeviceName(n string) { s.set(func(c *Settings) { c.DeviceName = n }) }
func (s *SettingsService) SetPort(p int) { s.set(func(c *Settings) { c.Port = p }) }
func (s *SettingsService) SetDownloadDir(d string) { s.set(func(c *Settings) { c.DownloadDir = d }) }
func (s *SettingsService) SetDownloadDirUri(u string) { s.set(func(c *Settings) { c.DownloadDirUri = u }) }
func (s *SettingsService) SetAutoAccept(b bool) { s.set(func(c *Settings) { c.AutoAccept = b }) }
func (s *SettingsService) SetTheme(t string) { s.set(func(c *Settings) { c.Theme = t }) }
func (s *SettingsService) SetDeviceName(n string) { s.set(func(c *Settings) { c.DeviceName = n }) }
func (s *SettingsService) SetPort(p int) { s.set(func(c *Settings) { c.Port = p }) }
func (s *SettingsService) SetDownloadDir(d string) { s.set(func(c *Settings) { c.DownloadDir = d }) }
func (s *SettingsService) SetDownloadDirUri(u string) {
s.set(func(c *Settings) { c.DownloadDirUri = u })
}
func (s *SettingsService) SetAutoAccept(b bool) { s.set(func(c *Settings) { c.AutoAccept = b }) }
func (s *SettingsService) SetTheme(t string) { s.set(func(c *Settings) { c.Theme = t }) }

func (s *SettingsService) set(mut func(*Settings)) {
s.mu.Lock()
Expand Down
Loading