Skip to content

Commit

Permalink
Move text receive window into bridge package as well
Browse files Browse the repository at this point in the history
Fixes #134
  • Loading branch information
Jacalz committed Jan 15, 2024
1 parent 0299e37 commit f979357
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 120 deletions.
114 changes: 107 additions & 7 deletions internal/transport/bridge/recv.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package bridge
import (
"path/filepath"
"sync/atomic"
"time"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
Expand All @@ -11,6 +12,8 @@ import (
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/Jacalz/rymdport/v3/internal/transport"
"github.com/Jacalz/rymdport/v3/internal/util"
"github.com/rymdport/wormhole/wormhole"
)

// RecvItem is the item that is being received
Expand Down Expand Up @@ -55,8 +58,9 @@ type RecvData struct {
Client *transport.Client
Window fyne.Window

items []*RecvItem
info recvInfoDialog
items []*RecvItem
info recvInfoDialog
textWindow textRecvWindow

deleting atomic.Bool
list *widget.List
Expand Down Expand Up @@ -141,17 +145,37 @@ func (d *RecvData) NewReceive(code string) {
d.list.Refresh()

go func(code string) {
if err := d.Client.NewReceive(code, item.setPath, item.update); err != nil {
msg, err := d.Client.NewReceive(code)
if err != nil {
d.Client.ShowNotification("Receive failed", "An error occurred when receiving the data.")
item.failed()
dialog.ShowError(err, d.Window)
} else if item.Name != "Text Snippet" {
d.Client.ShowNotification("Receive completed", "The contents were saved to "+filepath.Dir(item.URI.Path())+".")
item.done()
} else {
return
}

if msg.Type == wormhole.TransferText {
item.setPath("Text Snippet")
d.showTextWindow(msg.ReadText())

d.Client.ShowNotification("Receive completed", "The text was received successfully.")
item.update(0, 1) // Make sure that text updates progress.
item.done()
return
}

path := filepath.Join(d.Client.DownloadPath, msg.Name)
item.setPath(path)

err = d.Client.SaveToDisk(msg, path, item.update)
if err != nil {
d.Client.ShowNotification("Receive failed", "An error occurred when receiving the data.")
item.failed()
dialog.ShowError(err, d.Window)
return
}

d.Client.ShowNotification("Receive completed", "The contents were saved to "+filepath.Dir(item.URI.Path())+".")
item.done()
}(code)
}

Expand Down Expand Up @@ -198,3 +222,79 @@ type recvInfoDialog struct {
button *widget.Button
label *widget.Label
}

type textRecvWindow struct {
textEntry *widget.Entry
copyButton, saveButton *widget.Button
window fyne.Window
received string
fileSaveDialog *dialog.FileDialog
}

func (r *textRecvWindow) copy() {
r.window.Clipboard().SetContent(string(r.received))
}

func (r *textRecvWindow) interceptClose() {
r.window.Hide()
r.textEntry.SetText("")
}

func (r *textRecvWindow) saveFileToDisk(file fyne.URIWriteCloser, err error) {
if err != nil {
fyne.LogError("Error on selecting file to write to", err)
dialog.ShowError(err, r.window)
return
} else if file == nil {
return
}

if _, err := file.Write([]byte(r.received)); err != nil {
fyne.LogError("Error on writing text to the file", err)
dialog.ShowError(err, r.window)
}

if err := file.Close(); err != nil {
fyne.LogError("Error on closing text file", err)
dialog.ShowError(err, r.window)
}
}

func (r *textRecvWindow) save() {
now := time.Now().Format("2006-01-02T15:04") // TODO: Might want to use AppendFormat and strings.Builder
r.fileSaveDialog.SetFileName("received-" + now + ".txt")
r.fileSaveDialog.Resize(util.WindowSizeToDialog(r.window.Canvas().Size()))
r.fileSaveDialog.Show()
}

func (d *RecvData) createTextWindow() {
window := d.Client.App.NewWindow("Received Text")
window.SetCloseIntercept(d.textWindow.interceptClose)

d.textWindow = textRecvWindow{
window: window,
textEntry: &widget.Entry{MultiLine: true, Wrapping: fyne.TextWrapWord},
copyButton: &widget.Button{Text: "Copy", Icon: theme.ContentCopyIcon(), OnTapped: d.textWindow.copy},
saveButton: &widget.Button{Text: "Save", Icon: theme.DocumentSaveIcon(), OnTapped: d.textWindow.save},
fileSaveDialog: dialog.NewFileSave(d.textWindow.saveFileToDisk, window),
}

actionContainer := container.NewGridWithColumns(2, d.textWindow.copyButton, d.textWindow.saveButton)
window.SetContent(container.NewBorder(nil, actionContainer, nil, nil, d.textWindow.textEntry))
window.Resize(fyne.NewSize(400, 300))
}

// showTextWindow handles the creation of a window for displaying text content.
func (d *RecvData) showTextWindow(received string) {
if d.textWindow.window == nil {
d.createTextWindow()
}

d.textWindow.received = received
d.textWindow.textEntry.SetText(received)

win := d.textWindow.window
win.Show()
win.RequestFocus()
win.Canvas().Focus(d.textWindow.textEntry)
}
88 changes: 0 additions & 88 deletions internal/transport/display.go

This file was deleted.

32 changes: 11 additions & 21 deletions internal/transport/receiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,45 +27,33 @@ func bail(msg *wormhole.IncomingMessage, err error) error {
}

// NewReceive runs a receive using wormhole-william and handles types accordingly.
func (c *Client) NewReceive(code string, setPath func(string), progress func(int64, int64)) error {
func (c *Client) NewReceive(code string) (*wormhole.IncomingMessage, error) {
msg, err := c.Receive(context.Background(), code)
if err != nil {
fyne.LogError("Error on receiving data", err)
return bail(msg, err)
}

if msg.Type == wormhole.TransferText {
setPath("Text Snippet")
c.showTextReceiveWindow(msg.ReadText())
progress(0, 1) // Make sure that text updates progress.
return nil
return nil, bail(msg, err)
}

path := filepath.Join(c.DownloadPath, msg.Name)
setPath(path)

return c.SaveToDisk(msg, path, progress)
return msg, nil
}

// SaveToDisk saves the incomming file or directory transfer to the disk.
func (c *Client) SaveToDisk(msg *wormhole.IncomingMessage, path string, progress func(int64, int64)) (err error) {
func (c *Client) SaveToDisk(msg *wormhole.IncomingMessage, targetPath string, progress func(int64, int64)) (err error) {
contents := util.NewProgressReader(msg, progress, msg.TransferBytes)

if !c.OverwriteExisting {
if _, err := os.Stat(path); err == nil || os.IsExist(err) {
new, err := addFileIncrement(path)
if _, err := os.Stat(targetPath); err == nil || os.IsExist(err) {
targetPath, err = addFileIncrement(targetPath)
if err != nil {
fyne.LogError("Error on trying to create non-duplicate filename", err)
return bail(msg, err)
}

path = new
}
}

if msg.Type == wormhole.TransferFile {
var file *os.File
file, err = os.Create(path) // #nosec Path is cleaned by filepath.Join().
file, err = os.Create(targetPath) // #nosec Path is cleaned by filepath.Join().
if err != nil {
fyne.LogError("Error on creating file", err)
return bail(msg, err)
Expand Down Expand Up @@ -116,7 +104,7 @@ func (c *Client) SaveToDisk(msg *wormhole.IncomingMessage, path string, progress

err = zip.ExtractSafe(
util.NewProgressReaderAt(tmp, progress, contents.Max),
n, path, msg.UncompressedBytes, msg.FileCount,
n, targetPath, msg.UncompressedBytes, msg.FileCount,
)
if err != nil {
fyne.LogError("Error on unzipping contents", err)
Expand All @@ -128,6 +116,8 @@ func (c *Client) SaveToDisk(msg *wormhole.IncomingMessage, path string, progress
return
}

// addFileIncrement tries to add a number to the end of the filename if a duplicate exists.
// If it fails to do so after five tries, it till return the given path and an error.
func addFileIncrement(path string) (string, error) {
base := filepath.Dir(path)
ext := filepath.Ext(path)
Expand All @@ -149,5 +139,5 @@ func addFileIncrement(path string) (string, error) {
}
}

return "", errorTooManyDuplicates
return path, errorTooManyDuplicates
}
5 changes: 1 addition & 4 deletions internal/transport/transport.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,9 @@ import (
type Client struct {
wormhole.Client

// App is a reference to the currently running Fyne applciation.
// App is a reference to the currently running Fyne application.
App fyne.App

// Save a reference to the window to avoid creating a new one when sending and receiving text.
textRecvWindow textRecvWindow

// Notification holds the settings value for if we have notifications enabled or not.
Notifications bool

Expand Down

0 comments on commit f979357

Please sign in to comment.