From 37bab8054c6880b50161665b61e655bd50b3d538 Mon Sep 17 00:00:00 2001 From: Oleg Baranov Date: Sat, 9 Dec 2023 12:24:55 +0400 Subject: [PATCH] Core updated + UI improvements and new config settings --- app.go | 79 +++++++++++++++---- build/windows/installer/project.nsi | 2 +- config.go | 3 + core/api/client.go | 43 ++++++++-- core/client/storage.go | 11 ++- core/gostorage/client.go | 41 ++++++++-- core/upnp/forward.go | 10 ++- frontend/src/assets/images/icons/copy.svg | 4 + frontend/src/base.scss | 36 ++++++++- frontend/src/components/FilesTorrentMenu.tsx | 17 +++- frontend/src/components/InfoTorrentMenu.tsx | 14 +++- frontend/src/components/ModalAddTorrent.tsx | 2 +- .../src/components/ModalCreateTorrent.tsx | 24 +++++- frontend/src/components/ModalSettings.tsx | 2 +- frontend/src/components/Table.tsx | 6 ++ frontend/wailsjs/go/main/App.d.ts | 2 + frontend/wailsjs/go/main/App.js | 4 + go.mod | 6 +- go.sum | 8 +- 19 files changed, 267 insertions(+), 47 deletions(-) create mode 100644 frontend/src/assets/images/icons/copy.svg diff --git a/app.go b/app.go index f37fe0a..c73023e 100644 --- a/app.go +++ b/app.go @@ -9,6 +9,7 @@ import ( "github.com/tonutils/torrent-client/core/api" "github.com/tonutils/torrent-client/core/client" "github.com/tonutils/torrent-client/core/gostorage" + "github.com/tonutils/torrent-client/core/upnp" "github.com/tonutils/torrent-client/oshook" runtime2 "github.com/wailsapp/wails/v2/pkg/runtime" "github.com/xssnick/tonutils-go/adnl" @@ -18,6 +19,7 @@ import ( "os" "os/exec" "runtime" + "sort" "strings" "sync" "time" @@ -35,6 +37,10 @@ type App struct { openFileData []byte openFileHash string + lastCreateProgressReport time.Time + creationCtx context.Context + cancelCreation func() + mx sync.RWMutex } @@ -109,24 +115,32 @@ func (a *App) ShowWarnMsg(text string) { func (a *App) prepare() { oshook.HookStartup(a.openFile, a.openHash) - if !a.config.PortsChecked && !a.config.SeedMode { + if (!a.config.PortsChecked && !a.config.SeedMode) || a.config.FetchIPOnStartup { + log.Println("Trying to forward ports using UPnP") + + up, err := upnp.NewUPnP() + if err != nil { + log.Println("UPnP init failed", err.Error()) + } else { + if err = up.ForwardPortTCP(18889); err != nil { + log.Println("Port 18889 TCP forwarding failed:", err.Error()) + } + if err = up.ForwardPortUDP(13333); err != nil { + log.Println("Port 13333 UDP forwarding failed:", err.Error()) + } + } + ip, seed := CheckCanSeed() if seed { a.config.SeedMode = true a.config.ListenAddr = ip + ":13333" + log.Println("Static seed mode is enabled, ports are open.") + } else { + log.Println("Static seed mode was not activated, ports are closed.") } a.config.PortsChecked = true _ = a.config.SaveConfig(a.rootPath) } - - /*go func() { - // TODO: forward port - up, err := upnp.NewUPnP() - if err != nil { - return - // a.Throw(err) - } - }()*/ } var oncePrepare sync.Once @@ -154,15 +168,22 @@ func (a *App) ready(ctx context.Context) { } cfg := gostorage.Config{ - Key: ed25519.NewKeyFromSeed(a.config.Key), - ListenAddr: lAddr + ":" + addr[1], - ExternalIP: addr[0], - DownloadsPath: a.config.DownloadsPath, + Key: ed25519.NewKeyFromSeed(a.config.Key), + ListenAddr: lAddr + ":" + addr[1], + ExternalIP: addr[0], + DownloadsPath: a.config.DownloadsPath, + NetworkConfigPath: a.config.NetworkConfigPath, } if !a.config.SeedMode { cfg.ExternalIP = "" } + if cfg.ExternalIP == "0.0.0.0" { + a.ShowWarnMsg("external ip cannot be 0.0.0.0, disabling seed mode, " + + "change ip in settings to your real external ip") + cfg.ExternalIP = "" + } + var err error cl, err = gostorage.NewClient(a.rootPath+"/tonutils-storage-db", cfg) if err != nil { @@ -276,7 +297,8 @@ type TorrentCreateResult struct { } func (a *App) CreateTorrent(dir, description string) TorrentCreateResult { - hash, err := a.api.CreateTorrent(dir, description) + a.creationCtx, a.cancelCreation = context.WithCancel(a.ctx) + hash, err := a.api.CreateTorrent(a.creationCtx, dir, description, a.reportCreationProgress) if err != nil { log.Println(err.Error()) return TorrentCreateResult{Err: err.Error()} @@ -284,6 +306,24 @@ func (a *App) CreateTorrent(dir, description string) TorrentCreateResult { return TorrentCreateResult{Hash: hash} } +func (a *App) CancelCreateTorrent() { + println("CANCEL CREATION") + if a.cancelCreation != nil { + a.cancelCreation() + } +} + +func (a *App) reportCreationProgress(done, max uint64) { + now := time.Now() + if a.lastCreateProgressReport.Add(50 * time.Millisecond).After(now) { + // not refresh too often + return + } + a.lastCreateProgressReport = now + + runtime2.EventsEmit(a.ctx, "update-create-progress", fmt.Sprintf("%.2f", (float64(done)/float64(max))*100)) +} + func (a *App) ExportMeta(hash string) string { m, err := a.api.GetTorrentMeta(hash) if err != nil { @@ -359,6 +399,15 @@ func (a *App) GetPlainFiles(hash string) []api.PlainFile { if list == nil { return []api.PlainFile{} } + + sort.Slice(list, func(i, j int) bool { + return list[i].RawSize > list[j].RawSize + }) + + if len(list) > 1000 { + list = list[:1000] + } + return list } diff --git a/build/windows/installer/project.nsi b/build/windows/installer/project.nsi index 6d16fc0..6a2f260 100644 --- a/build/windows/installer/project.nsi +++ b/build/windows/installer/project.nsi @@ -22,7 +22,7 @@ Unicode true ## !define INFO_PROJECTNAME "MyProject" # Default "{{.Name}}" ## !define INFO_COMPANYNAME "MyCompany" # Default "{{.Info.CompanyName}}" ## !define INFO_PRODUCTNAME "MyProduct" # Default "{{.Info.ProductName}}" -## !define INFO_PRODUCTVERSION "1.0.1" # Default "{{.Info.ProductVersion}}" +## !define INFO_PRODUCTVERSION "1.1.0" # Default "{{.Info.ProductVersion}}" ## !define INFO_COPYRIGHT "Copyright" # Default "{{.Info.Copyright}}" ### ## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" diff --git a/config.go b/config.go index d1821b6..47e202d 100644 --- a/config.go +++ b/config.go @@ -24,6 +24,9 @@ type Config struct { DaemonControlAddr string PortsChecked bool + NetworkConfigPath string + FetchIPOnStartup bool + mx sync.Mutex } diff --git a/core/api/client.go b/core/api/client.go index 20c6529..910fb3b 100644 --- a/core/api/client.go +++ b/core/api/client.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/tonutils/torrent-client/core/client" "log" + "math/big" "sort" "strings" "sync" @@ -27,6 +28,7 @@ type PlainFile struct { Size string Downloaded string Progress float64 + RawSize int64 } type Torrent struct { @@ -40,6 +42,8 @@ type Torrent struct { Download string Path string PeersNum int + Uploaded string + Ratio string rawDowSpeed int64 rawDownloaded int64 @@ -59,6 +63,8 @@ type TorrentInfo struct { Path string Peers int AddedAt string + Uploaded string + Ratio string } type SpeedLimits struct { @@ -82,7 +88,7 @@ type StorageClient interface { GetTorrents(ctx context.Context) (*client.TorrentsList, error) AddByHash(ctx context.Context, hash []byte, dir string) (*client.TorrentFull, error) AddByMeta(ctx context.Context, meta []byte, dir string) (*client.TorrentFull, error) - CreateTorrent(ctx context.Context, dir, description string) (*client.TorrentFull, error) + CreateTorrent(ctx context.Context, dir, description string, progressCallback func(done uint64, max uint64)) (*client.TorrentFull, error) GetTorrentFull(ctx context.Context, hash []byte) (*client.TorrentFull, error) GetTorrentMeta(ctx context.Context, hash []byte) ([]byte, error) GetPeers(ctx context.Context, hash []byte) (*client.PeersList, error) @@ -91,6 +97,7 @@ type StorageClient interface { SetFilesPriority(ctx context.Context, hash []byte, names []string, priority int32) error GetSpeedLimits(ctx context.Context) (*client.SpeedLimits, error) SetSpeedLimits(ctx context.Context, download, upload int64) error + GetUploadStats(ctx context.Context, hash []byte) (uint64, error) } type API struct { @@ -153,7 +160,12 @@ func (a *API) SyncTorrents() error { continue } - tr := formatTorrent(full, len(peers.Peers), true) + uploaded, err := a.client.GetUploadStats(a.globalCtx, torrent.Hash) + if err != nil { + continue + } + + tr := formatTorrent(full, len(peers.Peers), true, uploaded) if tr == nil { continue } @@ -190,6 +202,13 @@ func toSz(sz int64) string { } } +func toRatio(uploaded, size uint64) string { + if size == 0 || uploaded == 0 { + return "0" + } + return new(big.Float).Quo(new(big.Float).SetUint64(uploaded), new(big.Float).SetUint64(size)).Text('f', 2) +} + func toSpeed(speed int64, zeroEmpty bool) string { if speed == 0 && zeroEmpty { return "" @@ -207,7 +226,7 @@ func toSpeed(speed int64, zeroEmpty bool) string { } } -func formatTorrent(full *client.TorrentFull, peersNum int, hide0Speed bool) *Torrent { +func formatTorrent(full *client.TorrentFull, peersNum int, hide0Speed bool, uploaded uint64) *Torrent { torrent := full.Torrent // newer object var dataSz, downloadedSz int64 for _, file := range full.Files { @@ -275,11 +294,13 @@ func formatTorrent(full *client.TorrentFull, peersNum int, hide0Speed bool) *Tor Upload: uplSpeed, Download: dowSpeed, Path: path, + PeersNum: peersNum, + Uploaded: toSz(int64(uploaded)), + Ratio: toRatio(uploaded, uint64(dataSz)), rawDowSpeed: int64(torrent.DownloadSpeed), rawDownloaded: downloadedSz, rawSize: dataSz, rawDescription: rawDesc, - PeersNum: peersNum, } } @@ -337,8 +358,8 @@ func (a *API) AddTorrentByMeta(meta []byte, rootDir string) error { return nil } -func (a *API) CreateTorrent(dir, description string) (string, error) { - t, err := a.client.CreateTorrent(a.globalCtx, dir, description) +func (a *API) CreateTorrent(ctx context.Context, dir, description string, progressCallback func(done uint64, max uint64)) (string, error) { + t, err := a.client.CreateTorrent(ctx, dir, description, progressCallback) if err != nil { return "", err } @@ -491,6 +512,7 @@ func (a *API) GetPlainFiles(hash string) ([]PlainFile, error) { Size: toSz(file.Size), Downloaded: toSz(file.DownloadedSize), Progress: progress, + RawSize: file.Size, }) } @@ -513,7 +535,12 @@ func (a *API) GetInfo(hash string) (*TorrentInfo, error) { return nil, err } - tr := formatTorrent(t, len(peers.Peers), false) + uploaded, err := a.client.GetUploadStats(a.globalCtx, hashBytes) + if err != nil { + return nil, err + } + + tr := formatTorrent(t, len(peers.Peers), false, uploaded) if tr == nil { return nil, fmt.Errorf("not initialized torrent") } @@ -550,6 +577,8 @@ func (a *API) GetInfo(hash string) (*TorrentInfo, error) { Path: tr.Path, Peers: len(peers.Peers), AddedAt: time.Unix(int64(t.Torrent.AddedAt), 0).Format("02 Jan 2006 15:04:05"), + Uploaded: tr.Uploaded, + Ratio: tr.Ratio, }, nil } diff --git a/core/client/storage.go b/core/client/storage.go index 1c5f3b5..3f07f31 100644 --- a/core/client/storage.go +++ b/core/client/storage.go @@ -107,7 +107,11 @@ func (s *StorageClient) AddByMeta(ctx context.Context, meta []byte, dir string) return nil, fmt.Errorf("unexpected response") } -func (s *StorageClient) CreateTorrent(ctx context.Context, dir, description string) (*TorrentFull, error) { +func (s *StorageClient) CreateTorrent(ctx context.Context, dir, description string, progressCallback func(done uint64, max uint64)) (*TorrentFull, error) { + if progressCallback != nil { + progressCallback(50, 100) + } + var res tl.Serializable err := s.client.QueryADNL(ctx, CreateTorrent{ Path: dir, @@ -164,6 +168,11 @@ func (s *StorageClient) GetTorrentMeta(ctx context.Context, hash []byte) ([]byte return nil, fmt.Errorf("unexpected response") } +func (s *StorageClient) GetUploadStats(ctx context.Context, hash []byte) (uint64, error) { + // not supported by daemon + return 0, nil +} + func (s *StorageClient) GetPeers(ctx context.Context, hash []byte) (*PeersList, error) { var res tl.Serializable err := s.client.QueryADNL(ctx, GetPeers{ diff --git a/core/gostorage/client.go b/core/gostorage/client.go index a85a159..c491683 100644 --- a/core/gostorage/client.go +++ b/core/gostorage/client.go @@ -1,20 +1,25 @@ package gostorage import ( + "bytes" "context" "crypto/ed25519" "encoding/hex" + "encoding/json" "fmt" + "github.com/pterm/pterm" "github.com/syndtr/goleveldb/leveldb" "github.com/tonutils/torrent-client/core/client" "github.com/xssnick/tonutils-go/adnl" "github.com/xssnick/tonutils-go/adnl/dht" "github.com/xssnick/tonutils-go/liteclient" "github.com/xssnick/tonutils-go/tl" + "github.com/xssnick/tonutils-storage/config" "github.com/xssnick/tonutils-storage/db" "github.com/xssnick/tonutils-storage/storage" "log" "net" + "os" "sort" ) @@ -23,6 +28,8 @@ type Config struct { ListenAddr string ExternalIP string DownloadsPath string + + NetworkConfigPath string } type Client struct { @@ -46,9 +53,23 @@ func NewClient(dbPath string, cfg Config) (*Client, error) { } } - lsCfg, err := liteclient.GetConfigFromUrl(context.Background(), "https://ton.org/global.config.json") - if err != nil { - return nil, fmt.Errorf("failed to download ton config: %w", err) + var lsCfg *liteclient.GlobalConfig + if cfg.NetworkConfigPath != "" { + lsCfg, err = liteclient.GetConfigFromFile(cfg.NetworkConfigPath) + if err != nil { + pterm.Error.Println("Failed to load ton network config from file:", err.Error()) + os.Exit(1) + } + } else { + lsCfg, err = liteclient.GetConfigFromUrl(context.Background(), "https://ton.org/global.config.json") + if err != nil { + pterm.Warning.Println("Failed to download ton config:", err.Error(), "; We will take it from static cache") + lsCfg = &liteclient.GlobalConfig{} + if err = json.NewDecoder(bytes.NewBufferString(config.FallbackNetworkConfig)).Decode(lsCfg); err != nil { + pterm.Error.Println("Failed to parse fallback ton config:", err.Error()) + os.Exit(1) + } + } } gate := adnl.NewGateway(cfg.Key) @@ -82,7 +103,7 @@ func NewClient(dbPath string, cfg Config) (*Client, error) { return nil, fmt.Errorf("failed to init downloader gateway: %w", err) } - srv := storage.NewServer(dhtClient, gate, cfg.Key, serverMode, true) + srv := storage.NewServer(dhtClient, gate, cfg.Key, serverMode) c.connector = storage.NewConnector(srv) c.storage, err = db.NewStorage(ldb, c.connector, false) @@ -168,13 +189,13 @@ func (c *Client) AddByMeta(ctx context.Context, meta []byte, dir string) (*clien return c.GetTorrentFull(ctx, tor.BagID) } -func (c *Client) CreateTorrent(ctx context.Context, path, description string) (*client.TorrentFull, error) { +func (c *Client) CreateTorrent(ctx context.Context, path, description string, progressCallback func(done uint64, max uint64)) (*client.TorrentFull, error) { rootPath, dir, files, err := c.storage.DetectFileRefs(path) if err != nil { return nil, fmt.Errorf("failed to read files: %w", err) } - it, err := storage.CreateTorrent(ctx, rootPath, dir, description, c.storage, c.connector, files) + it, err := storage.CreateTorrent(ctx, rootPath, dir, description, c.storage, c.connector, files, progressCallback) if err != nil { return nil, fmt.Errorf("failed to create bag: %w", err) } @@ -191,6 +212,14 @@ func (c *Client) GetTorrentFull(ctx context.Context, hash []byte) (*client.Torre return c.getTorrent(hash, true) } +func (c *Client) GetUploadStats(ctx context.Context, hash []byte) (uint64, error) { + t := c.storage.GetTorrent(hash) + if t == nil { + return 0, fmt.Errorf("torrent is not found") + } + return t.GetUploadStats(), nil +} + func (c *Client) getTorrent(hash []byte, withFiles bool) (*client.TorrentFull, error) { t := c.storage.GetTorrent(hash) if t == nil { diff --git a/core/upnp/forward.go b/core/upnp/forward.go index debdbb1..ce20388 100644 --- a/core/upnp/forward.go +++ b/core/upnp/forward.go @@ -17,7 +17,7 @@ func NewUPnP() (*UPnP, error) { return &UPnP{client: d}, nil } -func (u *UPnP) ForwardPort(port uint16) error { +func (u *UPnP) ForwardPortUDP(port uint16) error { err := u.client.Forward(port, "TON Torrent (Storage)", "UDP") if err != nil { return fmt.Errorf("failed to forward port using upnp: %w", err) @@ -25,6 +25,14 @@ func (u *UPnP) ForwardPort(port uint16) error { return nil } +func (u *UPnP) ForwardPortTCP(port uint16) error { + err := u.client.Forward(port, "TON Torrent (Storage)", "TCP") + if err != nil { + return fmt.Errorf("failed to forward port using upnp: %w", err) + } + return nil +} + func (u *UPnP) ExternalIP() (string, error) { ip, err := u.client.ExternalIP() if err != nil { diff --git a/frontend/src/assets/images/icons/copy.svg b/frontend/src/assets/images/icons/copy.svg new file mode 100644 index 0000000..ab5c735 --- /dev/null +++ b/frontend/src/assets/images/icons/copy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/frontend/src/base.scss b/frontend/src/base.scss index e73e702..fa05b46 100644 --- a/frontend/src/base.scss +++ b/frontend/src/base.scss @@ -359,6 +359,40 @@ img { background: rgba(118, 152, 187, 0.12); } +.create-torrent-loader-block { + margin-right: 12px; + display: flex; + flex-direction: column; + height: 60px; +} + +.create-progress-block { + width: 100%; + align-items: center; + height: 38px; + margin-top: auto; + margin-bottom: auto; + + display: flex; + flex-direction: column; +} + +.create-progress-bar-small { + width: 220px; + height: 100%; + background-color: $ton; + border-radius: 8px; + transition: width 0.2s; +} + +.create-progress-bar-form { + width: 220px; + height: 8px; + border-radius: 8px; + margin: auto auto auto auto; + background: rgba(118, 152, 187, 0.12); +} + .filters-menu { display: flex; flex-direction: column; @@ -692,7 +726,7 @@ img { } .files-table { - width: 95%; + width: 100%; margin-top: 5px; margin-left: 10px; margin-right: 10px; diff --git a/frontend/src/components/FilesTorrentMenu.tsx b/frontend/src/components/FilesTorrentMenu.tsx index 94f1349..a0be0cf 100644 --- a/frontend/src/components/FilesTorrentMenu.tsx +++ b/frontend/src/components/FilesTorrentMenu.tsx @@ -16,6 +16,7 @@ export interface FilesProps { interface State { files: FileItem[] + allShown: boolean } export class FilesTorrentMenu extends Component { @@ -24,6 +25,7 @@ export class FilesTorrentMenu extends Component { this.state = { files: [], + allShown: true } } @@ -41,7 +43,8 @@ export class FilesTorrentMenu extends Component { }) this.setState({ - files: newList + files: newList, + allShown: newList.length < 1000 }); }); } @@ -61,7 +64,7 @@ export class FilesTorrentMenu extends Component { for (let t of this.state.files) { items.push( {OpenFolderSelectFile(t.path).then()}}> - {t.name} + {t.name} {t.size} {t.downloaded}
@@ -72,6 +75,14 @@ export class FilesTorrentMenu extends Component { ); } + + if (!this.state.allShown) { + items.push( + + Too many files to render, please see others in directory + + ); + } return items; } @@ -79,7 +90,7 @@ export class FilesTorrentMenu extends Component { return - + diff --git a/frontend/src/components/InfoTorrentMenu.tsx b/frontend/src/components/InfoTorrentMenu.tsx index 5746be1..7e98737 100644 --- a/frontend/src/components/InfoTorrentMenu.tsx +++ b/frontend/src/components/InfoTorrentMenu.tsx @@ -22,6 +22,9 @@ interface State { added: string peers: string progress: string + + uploaded: string + ratio: string } export class InfoTorrentMenu extends Component { @@ -40,6 +43,8 @@ export class InfoTorrentMenu extends Component { added: "", peers: "", progress: "", + uploaded: "", + ratio: "", } } @@ -71,6 +76,8 @@ export class InfoTorrentMenu extends Component { status: tr.State, added: tr.AddedAt, peers: tr.Peers, + uploaded: tr.Uploaded, + ratio: tr.Ratio, }); }); } @@ -104,7 +111,12 @@ export class InfoTorrentMenu extends Component {
{this.state.downloadSpeed}
Remaining
{this.state.left}
- : ""} + : <> +
Uploaded
+
{this.state.uploaded}
+
Ratio
+
{this.state.ratio}
+ } : <> }
Downloaded
diff --git a/frontend/src/components/ModalAddTorrent.tsx b/frontend/src/components/ModalAddTorrent.tsx index 6ebfc00..fcd28b8 100644 --- a/frontend/src/components/ModalAddTorrent.tsx +++ b/frontend/src/components/ModalAddTorrent.tsx @@ -60,7 +60,7 @@ export class AddTorrentModal extends Component { startCheckFiles = (hash: string) => { // check header availability every 100 ms, and load files list when we get it - this.inter = setInterval(() => { + this.inter = window.setInterval(() => { CheckHeader(hash).then(has => { if (has) { GetFiles(hash).then((tree) => { diff --git a/frontend/src/components/ModalCreateTorrent.tsx b/frontend/src/components/ModalCreateTorrent.tsx index e073d68..9badf3e 100644 --- a/frontend/src/components/ModalCreateTorrent.tsx +++ b/frontend/src/components/ModalCreateTorrent.tsx @@ -1,6 +1,7 @@ import React, {Component} from 'react'; import {baseModal} from "./Modal"; -import {CreateTorrent, ExportMeta, OpenDir, OpenFolderSelectFile} from "../../wailsjs/go/main/App"; +import {CancelCreateTorrent, CreateTorrent, ExportMeta, OpenDir, OpenFolderSelectFile} from "../../wailsjs/go/main/App"; +import {EventsOff, EventsOn} from "../../wailsjs/runtime"; interface State { createdStage: boolean @@ -8,6 +9,8 @@ interface State { path: string name: string + creationProgress: string + hash?: string err?: string } @@ -25,9 +28,20 @@ export class CreateTorrentModal extends Component { + this.setState((current) => ({ ...current, creationProgress: progress })) + }) + } + componentWillUnmount() { + CancelCreateTorrent().then() + EventsOff("update-create-progress") + } + next = () => { if (!this.state.createdStage) { this.setState((current) => ({ ...current, canContinue: false, createdStage: true })) @@ -53,7 +67,13 @@ export class CreateTorrentModal extends ComponentTorrent successfully created!
: <>Creating torrent...
-
+
+
+ {this.state.creationProgress}% +
+
+
+
}
diff --git a/frontend/src/components/ModalSettings.tsx b/frontend/src/components/ModalSettings.tsx index e6c651f..835d8b6 100644 --- a/frontend/src/components/ModalSettings.tsx +++ b/frontend/src/components/ModalSettings.tsx @@ -181,7 +181,7 @@ export class SettingsModal extends Component {
- Version 1.0.1 + Version 1.1.0 { BrowserOpenURL("https://github.com/xssnick/TON-Torrent/releases") }}>Check updates diff --git a/frontend/src/components/Table.tsx b/frontend/src/components/Table.tsx index aa292b0..bfdac97 100644 --- a/frontend/src/components/Table.tsx +++ b/frontend/src/components/Table.tsx @@ -12,6 +12,7 @@ import Pause from "../../public/light/pause.svg"; import Close from "../../public/light/close.svg"; import OpenDir from "../assets/images/icons/open-folder.svg"; import Export from "../assets/images/icons/export.svg"; +import Copy from "../assets/images/icons/copy.svg"; export interface SelectedTorrent { hash: string @@ -223,10 +224,15 @@ export class Table extends Component { elems.push(
{ WantRemoveTorrent([t.id]).then(Refresh) }}>Remove
) + elems.push(
{ ExportMeta(t.id).then() }}>Export .tonbag
) + elems.push(
{ + navigator.clipboard.writeText(t.id).then(); + }}>Copy bag ID
) + this.setState((current) => ({ ...current, contextShow: true, contextItems: elems})); document.body.addEventListener("click", () => { diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index 61f519e..97b7233 100755 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -7,6 +7,8 @@ export function AddTorrentByHash(arg1:string):Promise; export function AddTorrentByMeta(arg1:string):Promise; +export function CancelCreateTorrent():Promise; + export function CheckHeader(arg1:string):Promise; export function CreateTorrent(arg1:string,arg2:string):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index cb3bafc..a557ecc 100755 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -10,6 +10,10 @@ export function AddTorrentByMeta(arg1) { return window['go']['main']['App']['AddTorrentByMeta'](arg1); } +export function CancelCreateTorrent() { + return window['go']['main']['App']['CancelCreateTorrent'](); +} + export function CheckHeader(arg1) { return window['go']['main']['App']['CheckHeader'](arg1); } diff --git a/go.mod b/go.mod index 586d59f..1f37290 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,11 @@ go 1.18 require ( github.com/audrenbdb/goforeground v0.0.0-20220126120304-39261aeee000 github.com/jcuga/go-upnp v0.0.0-20160830125909-492b17f02cbb + github.com/pterm/pterm v0.12.59 github.com/syndtr/goleveldb v1.0.0 github.com/wailsapp/wails/v2 v2.5.1 - github.com/xssnick/tonutils-go v1.8.0 - github.com/xssnick/tonutils-storage v0.1.1-0.20230817070924-cb10ad604327 + github.com/xssnick/tonutils-go v1.8.8-0.20231207120654-6860e0ce8447 + github.com/xssnick/tonutils-storage v0.3.1 ) require ( @@ -34,7 +35,6 @@ require ( github.com/oasisprotocol/curve25519-voi v0.0.0-20220328075252-7dd334e3daae // indirect github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/pterm/pterm v0.12.59 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/samber/lo v1.27.1 // indirect github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect diff --git a/go.sum b/go.sum index a706934..caad738 100644 --- a/go.sum +++ b/go.sum @@ -129,10 +129,10 @@ github.com/wailsapp/wails/v2 v2.5.1/go.mod h1:jbOZbcr/zm79PxXxAjP8UoVlDd9wLW3uDs github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -github.com/xssnick/tonutils-go v1.8.0 h1:HnGA374Un36Adhw3MNB0X/RCeckl4GGJ5ONU2Vaa6N8= -github.com/xssnick/tonutils-go v1.8.0/go.mod h1:rqfQ4jsLaFhUUvouz2hTTC02nQGszOhSps7tGAKRC8g= -github.com/xssnick/tonutils-storage v0.1.1-0.20230817070924-cb10ad604327 h1:HMatajwUjFJvhbYZUTmYonA7gieUjuUrDQOpnOvPHuc= -github.com/xssnick/tonutils-storage v0.1.1-0.20230817070924-cb10ad604327/go.mod h1:W6TmxrlYgLL7vMu5k475Mc346+JUt6ggQAlrDGTYulc= +github.com/xssnick/tonutils-go v1.8.8-0.20231207120654-6860e0ce8447 h1:7V55abz9fAoSrcIkbjvKZsi3kYHq2D0Tqd4ytcRYXhA= +github.com/xssnick/tonutils-go v1.8.8-0.20231207120654-6860e0ce8447/go.mod h1:rqfQ4jsLaFhUUvouz2hTTC02nQGszOhSps7tGAKRC8g= +github.com/xssnick/tonutils-storage v0.3.1 h1:8pWigaltK35qayijRhJAw4HsPJVuOj4mWVXrdh7eS2c= +github.com/xssnick/tonutils-storage v0.3.1/go.mod h1:XLXPeWsIuhI56nvqcPruNNThP3XpsUZomAhdAIcvKPI= golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
NameName Size Downloaded Progress