mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-06 00:25:43 +00:00
feat: support flutter web
This commit is contained in:
1 parent
c4a30dc4c2
commit
4d4d3b446a
39 files changed
+450
-299
No files matched your search
@@ -31,7 +31,7 @@ jobs:
|
||||
for goos in "${goos_arr[@]}"; do
|
||||
for goarch in "${goarch_arr[@]}"; do
|
||||
dir="dist/gopeed-$VERSION-$goos-$goarch/"
|
||||
(GOOS=$goos GOARCH=$goarch go build -tags nosqlite -ldflags="-s -w" -o $dir github.com/monkeyWie/gopeed-core/cmd/gopeed \
|
||||
(GOOS=$goos GOARCH=$goarch go build -tags nosqlite -ldflags="-s -w" -o $dir github.com/monkeyWie/gopeed/cmd/gopeed \
|
||||
&& cd $dir \
|
||||
&& zip -r ../zip/gopeed-$VERSION-$goos-$goarch.zip * \
|
||||
&& cd ../..) \
|
||||
|
||||
@@ -53,4 +53,4 @@ jobs:
|
||||
go-version: '^1.18'
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: go build github.com/monkeyWie/gopeed-core/cmd/gopeed
|
||||
run: go build github.com/monkeyWie/gopeed/cmd/gopeed
|
||||
@@ -1,6 +1,6 @@
|
||||
[](https://github.com/monkeyWie/gopeed-core/actions?query=workflow%3Atest)
|
||||
[](https://github.com/monkeyWie/gopeed/actions?query=workflow%3Atest)
|
||||
[](https://codecov.io/gh/monkeyWie/gopeed-core)
|
||||
[](https://github.com/monkeyWie/gopeed-core/releases)
|
||||
[](https://github.com/monkeyWie/gopeed/releases)
|
||||
|
||||
## gopeed
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
## 安装
|
||||
|
||||
```sh
|
||||
go install github.com/monkeyWie/gopeed-core
|
||||
go install github.com/monkeyWie/gopeed
|
||||
```
|
||||
|
||||
## 示例
|
||||
@@ -24,7 +24,7 @@ go install github.com/monkeyWie/gopeed-core
|
||||
|
||||
### 下载
|
||||
|
||||
前往[releases](https://github.com/monkeyWie/gopeed-core/releases)页面
|
||||
前往[releases](https://github.com/monkeyWie/gopeed/releases)页面
|
||||
|
||||
## TODO
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/download"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/pkg/download"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
// go build -ldflags="-w -s" -buildmode=c-shared -o bin/libgopeed.dll github.com/monkeyWie/gopeed-core/bind/desktop
|
||||
// go build -ldflags="-w -s" -buildmode=c-shared -o bin/libgopeed.dylib github.com/monkeyWie/gopeed-core/bind/desktop
|
||||
// go build -ldflags="-w -s" -buildmode=c-shared -o bin/libgopeed.dll github.com/monkeyWie/gopeed/bind/desktop
|
||||
// go build -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/macos//libgopeed.dylib github.com/monkeyWie/gopeed/bind/desktop
|
||||
package main
|
||||
|
||||
import "C"
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/rest"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/rest/model"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest/model"
|
||||
)
|
||||
|
||||
func main() {}
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
// gomobile bind -ldflags="-w -s" -o libgopeed.aar -target=android -androidapi 19 -javapkg=com.gopeed github.com/monkeyWie/gopeed-core/bind/mobile
|
||||
// gomobile bind -ldflags="-w -s" -o libgopeed.aar -target=android -androidapi 19 -javapkg=com.gopeed github.com/monkeyWie/gopeed/bind/mobile
|
||||
package libgopeed
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/rest"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/rest/model"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest/model"
|
||||
)
|
||||
|
||||
func Start(cfg string) (int, error) {
|
||||
|
||||
@@ -2,9 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/download"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/util"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/pkg/download"
|
||||
"github.com/monkeyWie/gopeed/pkg/util"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/monkeyWie/gopeed/pkg/rest"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest/model"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := rest.StartSync(&model.StartConfig{
|
||||
Network: "tcp",
|
||||
Address: "127.0.0.1:9999",
|
||||
Storage: model.StorageMem,
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
module github.com/monkeyWie/gopeed-core
|
||||
module github.com/monkeyWie/gopeed
|
||||
|
||||
go 1.18
|
||||
|
||||
@@ -36,8 +36,10 @@ require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/lispad/go-generics-tools v1.0.0 // indirect
|
||||
|
||||
@@ -106,6 +106,8 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
|
||||
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
|
||||
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
|
||||
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
@@ -159,6 +161,8 @@ github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORR
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190309154008-847fc94819f9/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
|
||||
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package fetcher
|
||||
|
||||
import (
|
||||
"github.com/monkeyWie/gopeed-core/internal/controller"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/internal/controller"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
)
|
||||
|
||||
// 对应协议的下载支持
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"github.com/anacrolix/torrent"
|
||||
"github.com/anacrolix/torrent/metainfo"
|
||||
"github.com/anacrolix/torrent/storage"
|
||||
"github.com/monkeyWie/gopeed-core/internal/controller"
|
||||
"github.com/monkeyWie/gopeed-core/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/util"
|
||||
"github.com/monkeyWie/gopeed/internal/controller"
|
||||
"github.com/monkeyWie/gopeed/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/pkg/util"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package bt
|
||||
|
||||
import (
|
||||
"github.com/monkeyWie/gopeed-core/internal/controller"
|
||||
"github.com/monkeyWie/gopeed-core/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/internal/controller"
|
||||
"github.com/monkeyWie/gopeed/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/monkeyWie/gopeed-core/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/util"
|
||||
"github.com/monkeyWie/gopeed/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/pkg/util"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"io"
|
||||
"mime"
|
||||
|
||||
@@ -2,10 +2,10 @@ package http
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/monkeyWie/gopeed-core/internal/controller"
|
||||
"github.com/monkeyWie/gopeed-core/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed-core/internal/test"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/internal/controller"
|
||||
"github.com/monkeyWie/gopeed/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed/internal/test"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package http
|
||||
|
||||
import "github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
import "github.com/monkeyWie/gopeed/pkg/base"
|
||||
|
||||
type chunk struct {
|
||||
Status base.Status
|
||||
|
||||
@@ -2,12 +2,12 @@ package download
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/monkeyWie/gopeed-core/internal/controller"
|
||||
"github.com/monkeyWie/gopeed-core/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed-core/internal/protocol/bt"
|
||||
"github.com/monkeyWie/gopeed-core/internal/protocol/http"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/util"
|
||||
"github.com/monkeyWie/gopeed/internal/controller"
|
||||
"github.com/monkeyWie/gopeed/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed/internal/protocol/bt"
|
||||
"github.com/monkeyWie/gopeed/internal/protocol/http"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/pkg/util"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -380,7 +380,7 @@ func (d *Downloader) GetTasks() []*Task {
|
||||
return d.tasks
|
||||
}
|
||||
|
||||
func (d *Downloader) GetConfig(v any) error {
|
||||
func (d *Downloader) GetConfig(v any) (bool, error) {
|
||||
return d.storage.Get(bucketConfig, "config", v)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package download
|
||||
|
||||
import (
|
||||
"github.com/monkeyWie/gopeed-core/internal/test"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/internal/test"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
+16
-7
@@ -11,7 +11,7 @@ import (
|
||||
type Storage interface {
|
||||
Setup(buckets []string) error
|
||||
Put(bucket string, key string, v any) error
|
||||
Get(bucket string, key string, v any) error
|
||||
Get(bucket string, key string, v any) (bool, error)
|
||||
List(bucket string, v any) error
|
||||
Pop(bucket string, key string, v any) error
|
||||
Delete(bucket string, key string) error
|
||||
@@ -67,9 +67,12 @@ func (n *MemStorage) Put(bucket string, key string, v any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n *MemStorage) Get(bucket string, key string, v any) error {
|
||||
changeValue(v, memData[bucket][key])
|
||||
return nil
|
||||
func (n *MemStorage) Get(bucket string, key string, v any) (bool, error) {
|
||||
if dv, ok := memData[bucket][key]; ok {
|
||||
changeValue(v, dv)
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (n *MemStorage) List(bucket string, v any) error {
|
||||
@@ -147,7 +150,7 @@ func (b *BoltStorage) Put(bucket string, key string, v any) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (b *BoltStorage) Get(bucket string, key string, v any) error {
|
||||
func (b *BoltStorage) Get(bucket string, key string, v any) (bool, error) {
|
||||
var data []byte
|
||||
err := b.db.View(func(tx *bbolt.Tx) error {
|
||||
b := tx.Bucket([]byte(bucket))
|
||||
@@ -155,9 +158,15 @@ func (b *BoltStorage) Get(bucket string, key string, v any) error {
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return false, err
|
||||
}
|
||||
return json.Unmarshal(data, v)
|
||||
if data == nil {
|
||||
return false, nil
|
||||
}
|
||||
if err := json.Unmarshal(data, v); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (b *BoltStorage) List(bucket string, v any) error {
|
||||
|
||||
@@ -2,9 +2,9 @@ package download
|
||||
|
||||
import (
|
||||
gonanoid "github.com/matoous/go-nanoid/v2"
|
||||
"github.com/monkeyWie/gopeed-core/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/util"
|
||||
"github.com/monkeyWie/gopeed/internal/fetcher"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/pkg/util"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
+4
-4
@@ -2,10 +2,10 @@ package rest
|
||||
|
||||
import (
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/download"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/rest/model"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/rest/util"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/pkg/download"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest/model"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest/util"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package model
|
||||
|
||||
import "github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
import "github.com/monkeyWie/gopeed/pkg/base"
|
||||
|
||||
type CreateTask struct {
|
||||
Res *base.Resource `json:"res"`
|
||||
|
||||
+76
-46
@@ -2,10 +2,11 @@ package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/download"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/rest/model"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/util"
|
||||
"github.com/monkeyWie/gopeed/pkg/download"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest/model"
|
||||
"github.com/monkeyWie/gopeed/pkg/util"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@@ -18,59 +19,34 @@ var (
|
||||
)
|
||||
|
||||
func Start(startCfg *model.StartConfig) (int, error) {
|
||||
if startCfg == nil {
|
||||
startCfg = &model.StartConfig{}
|
||||
}
|
||||
startCfg.Init()
|
||||
|
||||
downloadCfg := &download.DownloaderConfig{}
|
||||
if startCfg.Storage == model.StorageBolt {
|
||||
downloadCfg.Storage = download.NewBoltStorage(startCfg.StorageDir)
|
||||
} else {
|
||||
downloadCfg.Storage = download.NewMemStorage()
|
||||
}
|
||||
downloadCfg.RefreshInterval = startCfg.RefreshInterval
|
||||
Downloader = download.NewDownloader(downloadCfg.Init())
|
||||
if err := Downloader.Setup(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
serverConfig := getAndPutServerConfig(startCfg)
|
||||
var address string
|
||||
if startCfg.Network == "unix" {
|
||||
address = startCfg.Address
|
||||
util.SafeRemove(address)
|
||||
} else {
|
||||
address = net.JoinHostPort(serverConfig.Host, strconv.Itoa(serverConfig.Port))
|
||||
}
|
||||
|
||||
listener, err := net.Listen(startCfg.Network, address)
|
||||
srv, listener, err := buildServer(startCfg)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var r = mux.NewRouter()
|
||||
r.Methods(http.MethodPost).Path("/api/v1/resolve").HandlerFunc(Resolve)
|
||||
r.Methods(http.MethodPost).Path("/api/v1/tasks").HandlerFunc(CreateTask)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/tasks/{id}/pause").HandlerFunc(PauseTask)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/tasks/{id}/continue").HandlerFunc(ContinueTask)
|
||||
r.Methods(http.MethodDelete).Path("/api/v1/tasks/{id}").HandlerFunc(DeleteTask)
|
||||
r.Methods(http.MethodGet).Path("/api/v1/tasks/{id}").HandlerFunc(GetTask)
|
||||
r.Methods(http.MethodGet).Path("/api/v1/tasks").HandlerFunc(GetTasks)
|
||||
r.Methods(http.MethodGet).Path("/api/v1/config").HandlerFunc(GetConfig)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/config").HandlerFunc(PutConfig)
|
||||
|
||||
srv = &http.Server{Handler: r}
|
||||
go func() {
|
||||
if err := srv.Serve(listener); err != nil && err != http.ErrServerClosed {
|
||||
// TODO log
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
port := 0
|
||||
if addr, ok := listener.Addr().(*net.TCPAddr); ok {
|
||||
return addr.Port, nil
|
||||
port = addr.Port
|
||||
}
|
||||
return 0, nil
|
||||
return port, nil
|
||||
}
|
||||
|
||||
func StartSync(startCfg *model.StartConfig) error {
|
||||
srv, listener, err := buildServer(startCfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := srv.Serve(listener); err != nil && err != http.ErrServerClosed {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Stop() {
|
||||
@@ -86,11 +62,65 @@ func Stop() {
|
||||
}
|
||||
}
|
||||
|
||||
func buildServer(startCfg *model.StartConfig) (*http.Server, net.Listener, error) {
|
||||
if startCfg == nil {
|
||||
startCfg = &model.StartConfig{}
|
||||
}
|
||||
startCfg.Init()
|
||||
|
||||
downloadCfg := &download.DownloaderConfig{}
|
||||
if startCfg.Storage == model.StorageBolt {
|
||||
downloadCfg.Storage = download.NewBoltStorage(startCfg.StorageDir)
|
||||
} else {
|
||||
downloadCfg.Storage = download.NewMemStorage()
|
||||
}
|
||||
downloadCfg.RefreshInterval = startCfg.RefreshInterval
|
||||
Downloader = download.NewDownloader(downloadCfg.Init())
|
||||
if err := Downloader.Setup(); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
serverConfig := getAndPutServerConfig(startCfg)
|
||||
var address string
|
||||
if startCfg.Network == "unix" {
|
||||
address = startCfg.Address
|
||||
util.SafeRemove(address)
|
||||
} else {
|
||||
address = net.JoinHostPort(serverConfig.Host, strconv.Itoa(serverConfig.Port))
|
||||
}
|
||||
|
||||
listener, err := net.Listen(startCfg.Network, address)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var r = mux.NewRouter()
|
||||
r.Methods(http.MethodPost).Path("/api/v1/resolve").HandlerFunc(Resolve)
|
||||
r.Methods(http.MethodPost).Path("/api/v1/tasks").HandlerFunc(CreateTask)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/tasks/{id}/pause").HandlerFunc(PauseTask)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/tasks/{id}/continue").HandlerFunc(ContinueTask)
|
||||
r.Methods(http.MethodDelete).Path("/api/v1/tasks/{id}").HandlerFunc(DeleteTask)
|
||||
r.Methods(http.MethodGet).Path("/api/v1/tasks/{id}").HandlerFunc(GetTask)
|
||||
r.Methods(http.MethodGet).Path("/api/v1/tasks").HandlerFunc(GetTasks)
|
||||
r.Methods(http.MethodGet).Path("/api/v1/config").HandlerFunc(GetConfig)
|
||||
r.Methods(http.MethodPut).Path("/api/v1/config").HandlerFunc(PutConfig)
|
||||
|
||||
srv = &http.Server{Handler: handlers.CORS(
|
||||
handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"}),
|
||||
handlers.AllowedMethods([]string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}),
|
||||
handlers.AllowedOrigins([]string{"*"}),
|
||||
)(r)}
|
||||
return srv, listener, nil
|
||||
}
|
||||
|
||||
func getAndPutServerConfig(startCfg *model.StartConfig) *model.ServerConfig {
|
||||
var serverConfig model.ServerConfig
|
||||
err := Downloader.GetConfig(&serverConfig)
|
||||
// first start
|
||||
exist, err := Downloader.GetConfig(&serverConfig)
|
||||
if err != nil {
|
||||
// TODO log
|
||||
}
|
||||
// first start
|
||||
if !exist {
|
||||
if startCfg.Network == "tcp" {
|
||||
host, port, _ := net.SplitHostPort(startCfg.Address)
|
||||
serverConfig.Host = host
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/monkeyWie/gopeed-core/internal/test"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/base"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/download"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/rest/model"
|
||||
"github.com/monkeyWie/gopeed/internal/test"
|
||||
"github.com/monkeyWie/gopeed/pkg/base"
|
||||
"github.com/monkeyWie/gopeed/pkg/download"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest/model"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
@@ -2,7 +2,7 @@ package util
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/monkeyWie/gopeed-core/pkg/rest/model"
|
||||
"github.com/monkeyWie/gopeed/pkg/rest/model"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Code generated by cmd/cgo; DO NOT EDIT. */
|
||||
|
||||
/* package github.com/monkeyWie/gopeed-core/bind/desktop */
|
||||
/* package github.com/monkeyWie/gopeed/bind/desktop */
|
||||
|
||||
|
||||
#line 1 "cgo-builtin-export-prolog"
|
||||
|
||||
+16
-13
@@ -23,20 +23,23 @@ class _Client {
|
||||
if (_instance == null) {
|
||||
_instance = _Client._internal();
|
||||
var dio = Dio();
|
||||
dio.options.baseUrl = "http://127.0.0.1:${LibgopeedBoot.instance.port}";
|
||||
dio.options.baseUrl = "http://${LibgopeedBoot.instance.config.address}";
|
||||
_instance!.dio = dio;
|
||||
(_instance!.dio.httpClientAdapter as DefaultHttpClientAdapter)
|
||||
.onHttpClientCreate = (client) {
|
||||
if (LibgopeedBoot.instance.network == "unix") {
|
||||
client.connectionFactory =
|
||||
(Uri uri, String? proxyHost, int? proxyPort) {
|
||||
var address = InternetAddress(LibgopeedBoot.instance.address,
|
||||
type: InternetAddressType.unix);
|
||||
return Socket.startConnect(address, 0);
|
||||
};
|
||||
}
|
||||
return client;
|
||||
};
|
||||
if(_instance!.dio.httpClientAdapter is DefaultHttpClientAdapter){
|
||||
(_instance!.dio.httpClientAdapter as DefaultHttpClientAdapter)
|
||||
.onHttpClientCreate = (client) {
|
||||
if (LibgopeedBoot.instance.config.network == "unix") {
|
||||
client.connectionFactory =
|
||||
(Uri uri, String? proxyHost, int? proxyPort) {
|
||||
var address = InternetAddress(LibgopeedBoot.instance.config.address,
|
||||
type: InternetAddressType.unix);
|
||||
return Socket.startConnect(address, 0);
|
||||
};
|
||||
}
|
||||
return client;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import 'dart:async';
|
||||
|
||||
import '../libgopeed_boot.dart';
|
||||
|
||||
LibgopeedBoot create() => LibgopeedBootBrowser();
|
||||
|
||||
class LibgopeedBootBrowser implements LibgopeedBoot {
|
||||
late LibgopeedConfig _config;
|
||||
|
||||
LibgopeedBootBrowser() {
|
||||
_config = LibgopeedConfig();
|
||||
}
|
||||
|
||||
@override
|
||||
LibgopeedConfig get config => _config;
|
||||
|
||||
@override
|
||||
Future<void> start() async {}
|
||||
|
||||
@override
|
||||
Future<void> stop() async {}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:gopeed/core/common/libgopeed_channel.dart';
|
||||
import 'package:gopeed/util/util.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
import '../common/libgopeed_ffi.dart';
|
||||
import '../common/libgopeed_interface.dart';
|
||||
import '../common/start_config.dart';
|
||||
import '../ffi/libgopeed_bind.dart';
|
||||
import '../libgopeed_boot.dart';
|
||||
|
||||
LibgopeedBoot create() => LibgopeedBootNative();
|
||||
|
||||
class LibgopeedBootNative implements LibgopeedBoot {
|
||||
late LibgopeedConfig _config;
|
||||
late LibgopeedInterface _libgopeed;
|
||||
late SendPort _childSendPort;
|
||||
|
||||
LibgopeedBootNative() {
|
||||
_config = LibgopeedConfig();
|
||||
if (!Util.isDesktop()) {
|
||||
_libgopeed = LibgopeedChannel();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
LibgopeedConfig get config => _config;
|
||||
|
||||
@override
|
||||
Future<void> start() async {
|
||||
// if is debug mode,use local http server
|
||||
if (kDebugMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
var storageDir = "./";
|
||||
if (!Util.isUnix()) {
|
||||
// not support unix socket, use tcp
|
||||
_config.network = "tcp";
|
||||
_config.address = "127.0.0.1:0";
|
||||
} else {
|
||||
_config.network = "unix";
|
||||
if (Util.isDesktop()) {
|
||||
_config.address = LibgopeedBoot.unixSocketPath;
|
||||
} else if (Platform.isAndroid) {
|
||||
_config.address =
|
||||
"${(await getTemporaryDirectory()).path}/${LibgopeedBoot.unixSocketPath}";
|
||||
storageDir = (await getExternalStorageDirectory())?.path ?? "";
|
||||
}
|
||||
}
|
||||
final cfg = StartConfig(
|
||||
network: _config.network,
|
||||
address: _config.address,
|
||||
storage: 'bolt',
|
||||
storageDir: storageDir,
|
||||
refreshInterval: _config.refreshInterval);
|
||||
var port =
|
||||
Util.isDesktop() ? await _ffiStart(cfg) : await _libgopeed.start(cfg);
|
||||
if (_config.network == "tcp") {
|
||||
_config.address = "${_config.address.split(":")[0]}:$port";
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
if (Util.isDesktop()) {
|
||||
await _ffiStop();
|
||||
} else {
|
||||
await _libgopeed.stop();
|
||||
}
|
||||
}
|
||||
|
||||
_ffiInit() {
|
||||
if (Platform.isMacOS) {
|
||||
_libgopeed =
|
||||
LibgopeedFFi(LibgopeedBind(DynamicLibrary.open('libgopeed.dylib')));
|
||||
}
|
||||
}
|
||||
|
||||
// FFI run in isolate
|
||||
Future<int> _ffiStart(StartConfig cfg) async {
|
||||
var startCompleter = Completer<int>();
|
||||
|
||||
var mainReceive = ReceivePort();
|
||||
var isolate = await Isolate.spawn((SendPort sendPort) {
|
||||
_ffiInit();
|
||||
var childReceive = ReceivePort();
|
||||
sendPort.send(childReceive.sendPort);
|
||||
|
||||
childReceive.listen((message) async {
|
||||
late _Result result;
|
||||
try {
|
||||
if (message is _StartParam) {
|
||||
result = _StartResult();
|
||||
(result as _StartResult).port = await _libgopeed.start(message.cfg);
|
||||
}
|
||||
if (message is _StopParam) {
|
||||
result = _StopResult();
|
||||
await _libgopeed.stop();
|
||||
childReceive.close();
|
||||
Isolate.exit(sendPort);
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
result.exception = e;
|
||||
}
|
||||
sendPort.send(result);
|
||||
});
|
||||
}, mainReceive.sendPort);
|
||||
|
||||
var childCompleter = Completer<void>();
|
||||
mainReceive.listen((message) {
|
||||
if (message is SendPort) {
|
||||
_childSendPort = message;
|
||||
childCompleter.complete();
|
||||
}
|
||||
if (message is _StartResult) {
|
||||
if (message.exception != null) {
|
||||
startCompleter.completeError(message.exception!);
|
||||
} else {
|
||||
startCompleter.complete(message.port!);
|
||||
}
|
||||
}
|
||||
if (message is _StopResult) {
|
||||
isolate.kill();
|
||||
if (message.exception != null) {
|
||||
_stopCompleter.completeError(message.exception!);
|
||||
} else {
|
||||
_stopCompleter.complete();
|
||||
}
|
||||
}
|
||||
});
|
||||
await childCompleter.future;
|
||||
_childSendPort.send(_StartParam(cfg: cfg));
|
||||
return startCompleter.future;
|
||||
}
|
||||
|
||||
late Completer<void> _stopCompleter;
|
||||
|
||||
Future<void> _ffiStop() async {
|
||||
_stopCompleter = Completer<void>();
|
||||
_childSendPort.send(_StopParam());
|
||||
return _stopCompleter.future;
|
||||
}
|
||||
}
|
||||
|
||||
class _Result {
|
||||
Exception? exception;
|
||||
|
||||
_Result();
|
||||
}
|
||||
|
||||
class _StartParam {
|
||||
final StartConfig cfg;
|
||||
|
||||
_StartParam({required this.cfg});
|
||||
}
|
||||
|
||||
class _StartResult extends _Result {
|
||||
int? port;
|
||||
|
||||
_StartResult();
|
||||
}
|
||||
|
||||
class _StopParam {}
|
||||
|
||||
class _StopResult extends _Result {
|
||||
_StopResult();
|
||||
}
|
||||
@@ -1,171 +1,34 @@
|
||||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:isolate';
|
||||
import "./libgopeed_boot_stub.dart"
|
||||
if (dart.library.html) 'entry/libgopeed_boot_browser.dart'
|
||||
if (dart.library.io) 'entry/libgopeed_boot_native.dart';
|
||||
|
||||
import 'package:gopeed/core/common/libgopeed_channel.dart';
|
||||
import 'package:gopeed/core/common/libgopeed_ffi.dart';
|
||||
import 'package:gopeed/core/common/start_config.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
class LibgopeedConfig {
|
||||
late String network;
|
||||
late String address;
|
||||
late int refreshInterval;
|
||||
|
||||
import '../util/util.dart';
|
||||
import 'common/libgopeed_interface.dart';
|
||||
import 'ffi/libgopeed_bind.dart';
|
||||
LibgopeedConfig({
|
||||
this.network = "tcp",
|
||||
this.address = "127.0.0.1:9999",
|
||||
this.refreshInterval = 500,
|
||||
});
|
||||
}
|
||||
|
||||
const unixSocketPath = 'gopeed.sock';
|
||||
|
||||
class LibgopeedBoot {
|
||||
String network = "";
|
||||
String address = "";
|
||||
int port = 0;
|
||||
int refreshInterval = 250;
|
||||
|
||||
late LibgopeedInterface _libgopeed;
|
||||
late SendPort _childSendPort;
|
||||
abstract class LibgopeedBoot {
|
||||
static const unixSocketPath = 'gopeed.sock';
|
||||
|
||||
static LibgopeedBoot? _instance;
|
||||
|
||||
static LibgopeedBoot get instance {
|
||||
if (_instance == null) {
|
||||
_instance = LibgopeedBoot._internal();
|
||||
if (!Util.isDesktop()) {
|
||||
_instance!._libgopeed = LibgopeedChannel();
|
||||
}
|
||||
}
|
||||
_instance ??= LibgopeedBoot();
|
||||
return _instance!;
|
||||
}
|
||||
|
||||
LibgopeedBoot._internal();
|
||||
factory LibgopeedBoot() => create();
|
||||
|
||||
Future<void> start() async {
|
||||
var storageDir = "./";
|
||||
if (!Util.isUnix()) {
|
||||
// not support unix socket, use tcp
|
||||
network = "tcp";
|
||||
address = "127.0.0.1:0";
|
||||
} else {
|
||||
network = "unix";
|
||||
if (Util.isDesktop()) {
|
||||
address = unixSocketPath;
|
||||
} else if (Platform.isAndroid) {
|
||||
address = "${(await getTemporaryDirectory()).path}/$unixSocketPath";
|
||||
storageDir = (await getExternalStorageDirectory())?.path ?? "";
|
||||
}
|
||||
}
|
||||
final cfg = StartConfig(
|
||||
network: network,
|
||||
address: address,
|
||||
storage: 'bolt',
|
||||
storageDir: storageDir,
|
||||
refreshInterval: refreshInterval);
|
||||
if (Util.isDesktop()) {
|
||||
port = await _ffiStart(cfg);
|
||||
} else {
|
||||
port = await _libgopeed.start(cfg);
|
||||
}
|
||||
}
|
||||
Future<void> start();
|
||||
|
||||
Future<void> stop() async {
|
||||
if (Util.isDesktop()) {
|
||||
await _ffiStop();
|
||||
} else {
|
||||
await _libgopeed.stop();
|
||||
}
|
||||
}
|
||||
Future<void> stop();
|
||||
|
||||
_ffiInit() {
|
||||
if (Platform.isMacOS) {
|
||||
_libgopeed =
|
||||
LibgopeedFFi(LibgopeedBind(DynamicLibrary.open('libgopeed.dylib')));
|
||||
}
|
||||
}
|
||||
|
||||
// FFI run in isolate
|
||||
Future<int> _ffiStart(StartConfig cfg) async {
|
||||
var startCompleter = Completer<int>();
|
||||
|
||||
var mainReceive = ReceivePort();
|
||||
var isolate = await Isolate.spawn((SendPort sendPort) {
|
||||
_ffiInit();
|
||||
var childReceive = ReceivePort();
|
||||
sendPort.send(childReceive.sendPort);
|
||||
|
||||
childReceive.listen((message) async {
|
||||
late _Result result;
|
||||
try {
|
||||
if (message is _StartParam) {
|
||||
result = _StartResult();
|
||||
(result as _StartResult).port = await _libgopeed.start(message.cfg);
|
||||
}
|
||||
if (message is _StopParam) {
|
||||
result = _StopResult();
|
||||
await _libgopeed.stop();
|
||||
childReceive.close();
|
||||
Isolate.exit(sendPort);
|
||||
}
|
||||
} on Exception catch (e) {
|
||||
result.exception = e;
|
||||
}
|
||||
sendPort.send(result);
|
||||
});
|
||||
}, mainReceive.sendPort);
|
||||
|
||||
var childCompleter = Completer<void>();
|
||||
mainReceive.listen((message) {
|
||||
if (message is SendPort) {
|
||||
_childSendPort = message;
|
||||
childCompleter.complete();
|
||||
}
|
||||
if (message is _StartResult) {
|
||||
if (message.exception != null) {
|
||||
startCompleter.completeError(message.exception!);
|
||||
} else {
|
||||
startCompleter.complete(message.port!);
|
||||
}
|
||||
}
|
||||
if (message is _StopResult) {
|
||||
isolate.kill();
|
||||
if (message.exception != null) {
|
||||
_stopCompleter.completeError(message.exception!);
|
||||
} else {
|
||||
_stopCompleter.complete();
|
||||
}
|
||||
}
|
||||
});
|
||||
await childCompleter.future;
|
||||
_childSendPort.send(_StartParam(cfg: cfg));
|
||||
return startCompleter.future;
|
||||
}
|
||||
|
||||
late Completer<void> _stopCompleter;
|
||||
|
||||
Future<void> _ffiStop() async {
|
||||
_stopCompleter = Completer<void>();
|
||||
_childSendPort.send(_StopParam());
|
||||
return _stopCompleter.future;
|
||||
}
|
||||
}
|
||||
|
||||
class _Result {
|
||||
Exception? exception;
|
||||
|
||||
_Result();
|
||||
}
|
||||
|
||||
class _StartParam {
|
||||
final StartConfig cfg;
|
||||
|
||||
_StartParam({required this.cfg});
|
||||
}
|
||||
|
||||
class _StartResult extends _Result {
|
||||
int? port;
|
||||
|
||||
_StartResult();
|
||||
}
|
||||
|
||||
class _StopParam {}
|
||||
|
||||
class _StopResult extends _Result {
|
||||
_StopResult();
|
||||
LibgopeedConfig get config;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import 'libgopeed_boot.dart';
|
||||
|
||||
LibgopeedBoot create() => throw UnimplementedError();
|
||||
@@ -21,4 +21,4 @@ void main() async {
|
||||
themeMode: Setting.instance.themeMode,
|
||||
getPages: Routes.routes,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import 'dart:developer' as developer;
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -15,6 +14,7 @@ import 'package:permission_handler/permission_handler.dart';
|
||||
import 'package:rounded_loading_button/rounded_loading_button.dart';
|
||||
|
||||
import '../../routes/router.dart';
|
||||
import '../../util/util.dart';
|
||||
import '../../widget/directory_selector.dart';
|
||||
|
||||
class CreateView extends GetView<CreateController> {
|
||||
@@ -114,7 +114,7 @@ class CreateView extends GetView<CreateController> {
|
||||
width: width,
|
||||
child: Form(
|
||||
key: createFormKey,
|
||||
autovalidateMode: AutovalidateMode.always, //开启自动校验
|
||||
autovalidateMode: AutovalidateMode.always,
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
@@ -159,7 +159,7 @@ class CreateView extends GetView<CreateController> {
|
||||
try {
|
||||
if (createFormKey.currentState!.validate()) {
|
||||
downloadController.start();
|
||||
if (Platform.isAndroid) {
|
||||
if (Util.isAndroid()) {
|
||||
if (!await Permission.storage.request().isGranted) {
|
||||
Get.snackbar("错误", "需要开启存储权限");
|
||||
return;
|
||||
@@ -183,7 +183,7 @@ class CreateView extends GetView<CreateController> {
|
||||
}
|
||||
} catch (e) {
|
||||
Get.snackbar("错误", e.toString());
|
||||
developer.log(e.toString(), name: 'flutter');
|
||||
rethrow;
|
||||
} finally {
|
||||
downloadController.reset();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ class TaskController extends GetxController {
|
||||
|
||||
loadTab();
|
||||
_timer = Timer.periodic(
|
||||
Duration(milliseconds: LibgopeedBoot.instance.refreshInterval),
|
||||
Duration(milliseconds: LibgopeedBoot.instance.config.refreshInterval),
|
||||
(timer) async {
|
||||
loadTab();
|
||||
});
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:external_path/external_path.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:gopeed/api/api.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
@@ -48,7 +44,11 @@ class Setting {
|
||||
this.themeMode = ThemeMode.values.byName(themeMode);
|
||||
}
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
if(Util.isWeb()){
|
||||
downloadDir = "./";
|
||||
return;
|
||||
}
|
||||
if (Util.isAndroid()) {
|
||||
downloadDir =
|
||||
'${await ExternalPath.getExternalStoragePublicDirectory(ExternalPath.DIRECTORY_DOWNLOADS)}/com.gopeed';
|
||||
return;
|
||||
|
||||
@@ -3,11 +3,13 @@ import 'dart:io';
|
||||
import 'package:macos_secure_bookmarks/macos_secure_bookmarks.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'util.dart';
|
||||
|
||||
class MacSecureUtil {
|
||||
static const _bookmarkKey = "bookmark:";
|
||||
|
||||
static Future<void> saveBookmark(String dir) async {
|
||||
if (!Platform.isMacOS) {
|
||||
if (!Util.isMacos()) {
|
||||
return;
|
||||
}
|
||||
final secureBookmarks = SecureBookmarks();
|
||||
@@ -17,7 +19,7 @@ class MacSecureUtil {
|
||||
}
|
||||
|
||||
static Future<void> loadBookmark() async {
|
||||
if (!Platform.isMacOS) {
|
||||
if (!Util.isMacos()) {
|
||||
return;
|
||||
}
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
class Util {
|
||||
static String fmtByte(int byte) {
|
||||
if (byte < 1024) {
|
||||
@@ -21,11 +23,29 @@ class Util {
|
||||
return (dir == "" ? "" : "$dir/") + buildPath(path, name);
|
||||
}
|
||||
|
||||
static isWeb() {
|
||||
return kIsWeb;
|
||||
}
|
||||
|
||||
static isAndroid() {
|
||||
return !kIsWeb && Platform.isAndroid;
|
||||
}
|
||||
|
||||
static isMacos() {
|
||||
return !kIsWeb && Platform.isMacOS;
|
||||
}
|
||||
|
||||
static isDesktop() {
|
||||
if (kIsWeb) {
|
||||
return false;
|
||||
}
|
||||
return Platform.isWindows || Platform.isLinux || Platform.isMacOS;
|
||||
}
|
||||
|
||||
static isUnix() {
|
||||
if (kIsWeb) {
|
||||
return false;
|
||||
}
|
||||
return !Platform.isWindows;
|
||||
}
|
||||
}
|
||||
@@ -6,10 +6,12 @@
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
|
||||
@@ -4,10 +4,12 @@
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.downloads.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-write</key>
|
||||
<true/>
|
||||
<key>com.apple.security.files.bookmarks.app-scope</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.server</key>
|
||||
|
||||
Reference in new issue
Block a user