Refactor RealFileSystem to use WorkingDir, and ensure clean shutdown with FlushAll
This commit is contained in:
parent
ac2e0e444d
commit
1324772215
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -11,6 +11,7 @@
|
|||
*.jar
|
||||
./pad
|
||||
cmd/pad/pad
|
||||
cmd/pad/classes
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package st.wow.git.logbook;
|
|||
|
||||
import java.lang.Runnable;
|
||||
import java.lang.String;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.content.Context;
|
||||
|
|
@ -39,25 +40,49 @@ public class Permissions extends Fragment {
|
|||
});
|
||||
}
|
||||
|
||||
@Override public void onAttach(Context ctx) {
|
||||
super.onAttach(ctx);
|
||||
Log.d("gio", "onAttach()");
|
||||
if (ctx instanceof Activity) {
|
||||
Log.d("gio", "It's an Activity!");
|
||||
}
|
||||
if (ctx.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED || ctx.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||
Log.d("gio", "Requesting permissions");
|
||||
requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST);
|
||||
}
|
||||
if (!Environment.isExternalStorageManager()){
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
|
||||
Uri uri = Uri.fromParts("package", getActivity().getPackageName(), null);
|
||||
intent.setData(uri);
|
||||
startActivity(intent);
|
||||
}
|
||||
Log.d("gio", "Loading gio library");
|
||||
System.loadLibrary("gio");
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
Log.d("gio", "onAttach()");
|
||||
|
||||
if (!(context instanceof Activity)) {
|
||||
Log.w("gio", "Context is not an Activity");
|
||||
return;
|
||||
}
|
||||
|
||||
Activity activity = (Activity) context;
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
|
||||
if (context.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
|
||||
!= PackageManager.PERMISSION_GRANTED) {
|
||||
requestPermissions(
|
||||
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
|
||||
PERMISSIONS_REQUEST
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
||||
&& !Environment.isExternalStorageManager()) {
|
||||
Log.d("gio", "Requesting all files access");
|
||||
Intent intent = new Intent(
|
||||
Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION,
|
||||
Uri.parse("package:" + activity.getPackageName())
|
||||
);
|
||||
if (intent.resolveActivity(activity.getPackageManager()) != null) {
|
||||
startActivity(intent);
|
||||
} else {
|
||||
Intent fallback = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
|
||||
if (fallback.resolveActivity(activity.getPackageManager()) != null) {
|
||||
startActivity(fallback);
|
||||
} else {
|
||||
Log.e("gio", "No activity found for all files access settings");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.d("gio", "Loading gio library");
|
||||
System.loadLibrary("gio");
|
||||
}
|
||||
|
||||
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
type JNIEnv = C.JNIEnv
|
||||
var (
|
||||
startpath="/storage/emulated/0/Documents"
|
||||
startpath="/storage/emulated/0/Notes"
|
||||
jvm uintptr
|
||||
theJVM *C.JavaVM
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import (
|
|||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"gioui.org/app"
|
||||
|
|
@ -41,12 +40,8 @@ func run(w *app.Window) error {
|
|||
rootDir := flag.String("root", startpath, "root directory for the filesystem")
|
||||
flag.Parse()
|
||||
|
||||
abs, err := filepath.Abs(*rootDir)
|
||||
if err != nil {
|
||||
log.Fatalf("invalid root directory: %v", err)
|
||||
}
|
||||
fs := &real.RealFileSystem{Root: abs}
|
||||
log.Printf("using filesystem at %s", abs)
|
||||
fs := real.NewRealFileSystem(*rootDir)
|
||||
log.Printf("using filesystem at %s", fs.WorkingDir)
|
||||
|
||||
logic := editor.NewLogic(fs)
|
||||
renderer := ui.New(ui.Theme{FontSize: 14}, shaper, logic.State())
|
||||
|
|
@ -62,6 +57,7 @@ func run(w *app.Window) error {
|
|||
for {
|
||||
switch e := w.Event().(type) {
|
||||
case app.DestroyEvent:
|
||||
logic.Shutdown()
|
||||
return e.Err
|
||||
case app.ConfigEvent:
|
||||
// ConfigEvent: raw pixel dimensions only.
|
||||
|
|
|
|||
|
|
@ -413,3 +413,10 @@ func (l *Logic) FlushAll() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shutdown gracefully shuts down the logic goroutine and worker pool.
|
||||
func (l *Logic) Shutdown() {
|
||||
l.FlushAll()
|
||||
l.Done()
|
||||
l.workerPool.Stop()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,24 @@ import (
|
|||
|
||||
// RealFileSystem implements the pool.FileSystem interface using the real OS filesystem.
|
||||
type RealFileSystem struct {
|
||||
Root string
|
||||
WorkingDir string
|
||||
}
|
||||
|
||||
// NewRealFileSystem creates a RealFileSystem rooted at the given working directory.
|
||||
// If workingDir is empty, it defaults to "/".
|
||||
func NewRealFileSystem(workingDir string) *RealFileSystem {
|
||||
if workingDir == "" {
|
||||
workingDir = "/"
|
||||
}
|
||||
abs, err := filepath.Abs(workingDir)
|
||||
if err != nil {
|
||||
abs = workingDir
|
||||
}
|
||||
return &RealFileSystem{WorkingDir: abs}
|
||||
}
|
||||
|
||||
func (fs *RealFileSystem) ReadDir(path string) ([]types.DirEntry, error) {
|
||||
entries, err := os.ReadDir(filepath.Join(fs.Root, path))
|
||||
entries, err := os.ReadDir(filepath.Join(fs.WorkingDir, path))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -25,21 +38,21 @@ func (fs *RealFileSystem) ReadDir(path string) ([]types.DirEntry, error) {
|
|||
}
|
||||
|
||||
func (fs *RealFileSystem) DirExists(path string) bool {
|
||||
info, err := os.Stat(filepath.Join(fs.Root, path))
|
||||
info, err := os.Stat(filepath.Join(fs.WorkingDir, path))
|
||||
return err == nil && info.IsDir()
|
||||
}
|
||||
|
||||
func (fs *RealFileSystem) FileExists(path string) bool {
|
||||
info, err := os.Stat(filepath.Join(fs.Root, path))
|
||||
info, err := os.Stat(filepath.Join(fs.WorkingDir, path))
|
||||
return err == nil && !info.IsDir()
|
||||
}
|
||||
|
||||
func (fs *RealFileSystem) ReadFile(path string) ([]byte, error) {
|
||||
return os.ReadFile(filepath.Join(fs.Root, path))
|
||||
return os.ReadFile(filepath.Join(fs.WorkingDir, path))
|
||||
}
|
||||
|
||||
func (fs *RealFileSystem) ReadFileAt(path string, offset, size int) ([]byte, error) {
|
||||
fullPath := filepath.Join(fs.Root, path)
|
||||
fullPath := filepath.Join(fs.WorkingDir, path)
|
||||
f, err := os.Open(fullPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -61,7 +74,7 @@ func (fs *RealFileSystem) WriteFile(path string, content []byte) error {
|
|||
|
||||
func (fs *RealFileSystem) WriteFileAtomic(path string, content []byte) error {
|
||||
// Atomic write implementation
|
||||
fullPath := filepath.Join(fs.Root, path)
|
||||
fullPath := filepath.Join(fs.WorkingDir, path)
|
||||
// Temp file in the same directory as the target to ensure same filesystem rename
|
||||
tmpPath := filepath.Join(filepath.Dir(fullPath), "."+filepath.Base(path)+".tmp")
|
||||
|
||||
|
|
@ -77,11 +90,11 @@ func (fs *RealFileSystem) WriteFileAtomic(path string, content []byte) error {
|
|||
}
|
||||
|
||||
func (fs *RealFileSystem) DeleteFile(path string) error {
|
||||
return os.Remove(filepath.Join(fs.Root, path))
|
||||
return os.Remove(filepath.Join(fs.WorkingDir, path))
|
||||
}
|
||||
|
||||
func (fs *RealFileSystem) CreateDir(path string) error {
|
||||
return os.MkdirAll(filepath.Join(fs.Root, path), 0755)
|
||||
return os.MkdirAll(filepath.Join(fs.WorkingDir, path), 0755)
|
||||
}
|
||||
|
||||
// realDirEntry wraps os.DirEntry
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user