137 lines
3.2 KiB
Go
137 lines
3.2 KiB
Go
|
package mobile
|
||
|
|
||
|
import (
|
||
|
"io"
|
||
|
|
||
|
"fyne.io/fyne/v2"
|
||
|
"fyne.io/fyne/v2/internal/driver/mobile/app"
|
||
|
"fyne.io/fyne/v2/storage"
|
||
|
)
|
||
|
|
||
|
type fileOpen struct {
|
||
|
io.ReadCloser
|
||
|
uri fyne.URI
|
||
|
done func()
|
||
|
}
|
||
|
|
||
|
func (f *fileOpen) URI() fyne.URI {
|
||
|
return f.uri
|
||
|
}
|
||
|
|
||
|
func fileReaderForURI(u fyne.URI) (fyne.URIReadCloser, error) {
|
||
|
file := &fileOpen{uri: u}
|
||
|
read, err := nativeFileOpen(file)
|
||
|
if read == nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
file.ReadCloser = read
|
||
|
return file, err
|
||
|
}
|
||
|
|
||
|
func mobileFilter(filter storage.FileFilter) *app.FileFilter {
|
||
|
mobile := &app.FileFilter{}
|
||
|
|
||
|
if f, ok := filter.(*storage.MimeTypeFileFilter); ok {
|
||
|
mobile.MimeTypes = f.MimeTypes
|
||
|
} else if f, ok := filter.(*storage.ExtensionFileFilter); ok {
|
||
|
mobile.Extensions = f.Extensions
|
||
|
} else if filter != nil {
|
||
|
fyne.LogError("Custom filter types not supported on mobile", nil)
|
||
|
}
|
||
|
|
||
|
return mobile
|
||
|
}
|
||
|
|
||
|
type hasOpenPicker interface {
|
||
|
ShowFileOpenPicker(func(string, func()), *app.FileFilter)
|
||
|
}
|
||
|
|
||
|
// ShowFileOpenPicker loads the native file open dialog and returns the chosen file path via the callback func.
|
||
|
func ShowFileOpenPicker(callback func(fyne.URIReadCloser, error), filter storage.FileFilter) {
|
||
|
drv := fyne.CurrentApp().Driver().(*mobileDriver)
|
||
|
if a, ok := drv.app.(hasOpenPicker); ok {
|
||
|
a.ShowFileOpenPicker(func(uri string, closer func()) {
|
||
|
if uri == "" {
|
||
|
callback(nil, nil)
|
||
|
return
|
||
|
}
|
||
|
f, err := fileReaderForURI(nativeURI(uri))
|
||
|
if f != nil {
|
||
|
f.(*fileOpen).done = closer
|
||
|
}
|
||
|
callback(f, err)
|
||
|
}, mobileFilter(filter))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// ShowFolderOpenPicker loads the native folder open dialog and calls back the chosen directory path as a ListableURI.
|
||
|
func ShowFolderOpenPicker(callback func(fyne.ListableURI, error)) {
|
||
|
filter := storage.NewMimeTypeFileFilter([]string{"application/x-directory"})
|
||
|
drv := fyne.CurrentApp().Driver().(*mobileDriver)
|
||
|
if a, ok := drv.app.(hasOpenPicker); ok {
|
||
|
a.ShowFileOpenPicker(func(path string, _ func()) {
|
||
|
if path == "" {
|
||
|
callback(nil, nil)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
uri, err := storage.ParseURI(path)
|
||
|
if err != nil {
|
||
|
callback(nil, err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
callback(listerForURI(uri))
|
||
|
}, mobileFilter(filter))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
type fileSave struct {
|
||
|
io.WriteCloser
|
||
|
uri fyne.URI
|
||
|
done func()
|
||
|
}
|
||
|
|
||
|
func (f *fileSave) URI() fyne.URI {
|
||
|
return f.uri
|
||
|
}
|
||
|
|
||
|
func fileWriterForURI(u fyne.URI) (fyne.URIWriteCloser, error) {
|
||
|
file := &fileSave{uri: u}
|
||
|
write, err := nativeFileSave(file)
|
||
|
if write == nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
file.WriteCloser = write
|
||
|
return file, err
|
||
|
}
|
||
|
|
||
|
type hasSavePicker interface {
|
||
|
ShowFileSavePicker(func(string, func()), *app.FileFilter, string)
|
||
|
}
|
||
|
|
||
|
// ShowFileSavePicker loads the native file save dialog and returns the chosen file path via the callback func.
|
||
|
func ShowFileSavePicker(callback func(fyne.URIWriteCloser, error), filter storage.FileFilter, filename string) {
|
||
|
drv := fyne.CurrentApp().Driver().(*mobileDriver)
|
||
|
if a, ok := drv.app.(hasSavePicker); ok {
|
||
|
a.ShowFileSavePicker(func(path string, closer func()) {
|
||
|
if path == "" {
|
||
|
callback(nil, nil)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
uri, err := storage.ParseURI(path)
|
||
|
if err != nil {
|
||
|
callback(nil, err)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
f, err := fileWriterForURI(uri)
|
||
|
if f != nil {
|
||
|
f.(*fileSave).done = closer
|
||
|
}
|
||
|
callback(f, err)
|
||
|
}, mobileFilter(filter), filename)
|
||
|
}
|
||
|
}
|