GithubHelp home page GithubHelp logo

warpdesign / react-explorer Goto Github PK

View Code? Open in Web Editor NEW
204.0 5.0 33.0 7.39 MB

File manager written in TypeScript, React, Blueprint and packaged with Electron

License: MIT License

HTML 0.37% TypeScript 96.18% CSS 2.30% JavaScript 1.14%
react typescript blueprint mobx electron linux macos filemanager

react-explorer's Introduction

File manager written in TypeScript & React

master Tests

React-Explorer

Features

  • Split-view window
  • Tabs support
  • Fully keyboard controlled
  • Fully localized (French & English available)
  • Dark Mode with automatic detection (macOS Mojave)
  • Open a terminal from any folder
  • Plugin-based filesystem support
  • WSL detection on Windows

Feature tour

Dark theme automatic detection (macOS Mojave)

React-Explorer will automatically switch to dark-theme when it's detected:

dark-theme

Create and read folder

By pressing ctrl (Linux/Win) or cmd the folder you create will be automatically read:

create-read-folder

Create nested folders

You can create several folders at once by separating them with a forward-slash:

nested-folders

Quick access to parent folders

By right-clicking on a tab's icon you can quickly get access to the parents of the currend folder:

parent-folders

WSL support

React-Explorer will automatically detect and show the list of Linux distributions installed using WSL on Windows:

parent-folders

Requirements

React-Explorer works on any modern Windows, Mac or Linux computer.

Building for local development

In order to build React-Explorer you need to have installed nodejs.

Once installed, building React-Explorer is as easy as typing:

npm install && npm run build

This will build a development package.

In order to run in locally without having to create a native executable, you can then type:

npx electron ./build/main.js

Building binary packages

In order to build binary packages, simply type the following:

npm run dist

This will build packaged binaries of React Explorer into the dist folder for every supported platform.

React-Explorer can also be built for a single patform. For example, to build only the Windows binaries, type:

npm run dist-win

Localization

React-Explorer is fully localized using .json files. Right now, English and French are available.

Adding a new language to React-Explorer is easy: simply duplicate one of the file found in src/locale/lang directory.

The new file should have the name code.json where code is a valid language code, for example: ja.json to add support for Japanese.

Tests

Unit testing

React-Explorer has both unit tests (using Jest) and end to end tests (using Cypress).

To run unit tests simply type:

npm test

This will start Jest and run every spec files found in src. Every test file can be found next to the component it is testing.

End to End testing

End to end tests are using Cypress and are in the separate e2e directory. You must install & configure Cypress before running E2E tests. This needs to be done one once using the following commands:

cd e2e && npm install && cd ..

The first time you run the tests, you also need to install cypress dependencies:

npm install

Since end to end tests need to run Electron-Explorer outside of Electron, a special build needs to be created that stubs some Electron APIs. To create this build, simply type:

npm run build

This will create a new Electron-Explorer in the build-e2e directory.

You may also type npm run watch if you want to rebuild automatically the e2e build after a change has been detected inside the sources.

For React-Explorer to run without Electron, a local webserver needs to be started before running the tests:

npm run server

Now, simply type: npm run cypress:run or npm run cypress:open.

How to develop a new Plugin

React-Explorer has been written so that it can easily be extended using plugins.

As a starting point you may use the FsGeneric skeleton.

Acknowledgments

React-Explorer makes use of the following tools/components:

Licence

React-Explorer is licenced under the MIT licence.

react-explorer's People

Contributors

dependabot[bot] avatar prajwalhaniya avatar warpdesign avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

react-explorer's Issues

[Tabs] Right click on icon shows the wrong path menu

How to reproduce?

  • open two tabs in a different folder
  • right-click on the icon of the inactive tab

What happens?

The menu shows the path of the active tab.

What should happen?

The menu should show the path of the active tab.

FileCache: sync same caches

If two tabs are opened pointing to the same directory, two different caches will be used.

If a file operation happens in one of the tab (eg. delete a folder), only this tab will be updated.

Fix: when refreshing/updating a cache, keep in sync any cache with the same path.

Dev: crash when exiting

The following exception is thrown from time to time when attempting to exit the app by clicking on the close button (may happen in other situation as well):

/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Helper.app/Contents/MacOS/Electron Helper[69504]: ../../vendor/node/src/fs_event_wrap.cc:91:static void node::(anonymous namespace)::FSEventWrap::GetInitialized(const FunctionCallbackInfo<v8::Value> &): Assertion `wrap != nullptr' failed.
 1: node::Abort() [/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib]
 2: node::Assert(char const* const (*) [4]) [/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib]
 3: _register_fs_event_wrap() [/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib]
 4: v8::internal::VirtualMemory::TakeControl(v8::internal::VirtualMemory*) [/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib]
 5: v8::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, v8::internal::BasicBlockProfiler const&) [/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib]
 6: v8::internal::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, v8::internal::BasicBlockProfiler const&) [/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib]
 7: v8::internal::Object::GetProperty(v8::internal::LookupIterator*) [/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib]
 8: v8::internal::Isolate::fuzzer_rng() [/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib]
 9: v8::internal::Isolate::fuzzer_rng() [/Users/leo/dev/react-explorer/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libnode.dylib]
10: 0x1761f841fd
exit request and no force: sending back exitRequest
exit request and no force: sending back exitRequest
^Cbefore quit

When this happens, the app refuses to quit (the windows stay opened).

Investigate WSL2 support

Build 18917 of Windows 10 adds support for WSL2. In this version, you may access your Linux files by typing explorer /.

Investigate supporting this new local scheme on Windows 10.

Using native modules

Some little problems trying to use native modules...

drivelist

Native module drivelist (or one of its deps) appears to use eval(). Changing the Content-Security-Policy as is fixes the problem, but we don't want this:

    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval'">

electron-rebuild (dev mode)

The drivelist native module has to be rebuilt: electron-rebuild can do that, but it places the drivelist.node build file in node_modules/drivelist/build/darwin-x64-64/drivelist.node and the dev electron doesn't look there so do not find the file.

Manually copying it in one of the searchpath (eg. build/) fixes the problem.

On Windows, the module has first to be rebuilt using:

npm install --save-dev electron-rebuild

# Every time you run "npm install", run this
./node_modules/.bin/electron-rebuild

# On Windows if you have trouble, try:
.\node_modules\.bin\electron-rebuild.cmd

And then the file found inside node_modules\drivelist\bin\win32-x64-64\drivelist.node has to be copied into build.

electron-rebuild (packaged mode)

Built app won't include the built native module and at runtime, following error will appear:

Uncaught (in promise) TypeError: Cannot read property 'indexOf' of undefined

The problem appears to be in bindings or electron-builder, I'm not sure where to look.

Bug opened in bindings: TooTallNate/node-bindings#54

Update: the problem is actually related to the webpack's optimizer that strips some code. See: TooTallNate/node-bindings#61 (comment)

Settings: default path error stays after entering an invalid path

  1. open the settings dialog
  2. change the terminal path and enter an invalid value (non-existing path)
  3. press escape to close the dialog
  4. open the dialog again: the error is still there (does it mean an invalid path has been saved?)
  5. trying to enter a valid path doesn't remove the error

Favorites List: alt + click = open in other tab

Right now:

  • left click on fav: opens specified link into active view/tab

Suggestion:

  • left click on fav: same
  • ctrl + left (win/linux)/alt + left (mac) click on fav: open on other tab (switching to dual view if needed)

Status bar shows forbidden cursor

Since the status bar's disable property is set, when moving the cursor over the status bar, the forbidden cursor is displayed.

Default cursor pointer should be set instead.

ctrl + a selects all text

When no input element is active, pressing ctrl + a should only select every file in the active view, and prevent default DOM action (ie: select all text within the page).

This happens on Windows (and probably Linux), but not macOS since selectAll has some specific code on this OS.

Show scrollbars on Linux/Windows

Current version of React-Explorer uses overlayScrollbars which are hidding big ugly scrollbars on Windows/Linux. Problem scrollbars seem to be hidden and using touchpad to scroll does not seem to make them appear.

Using SimpleBar could be a good idea.

Also, the overlayScrollbars of Chrome was removed in Chrome 78 so will likely be removed from Electron as well.

Move to Electron 7.0

Electron 7.0 adds support for Windows on ARM64: this alone is enough to make the move.

There seem to be some breaking changes:

  • menu.setApplicationMenu() has been removed
  • ipc communication with remote is deprecated in favor of invoke()

IPC communication

We are using ipcRenderer.send():

// Main
ipcMain.on('read-file', async (event, path) => {
  if (!pathIsOK(path))
    return event.sender.send('read-file-complete', 'forbidden')
  const buf = await fs.promises.readFile(path)
  event.sender.send('read-file-complete', null, buf)
})
// Renderer
ipcRenderer.send('read-file', '/path/to/file')
ipcRenderer.on('read-file-complete', (event, err, data) => {
  // ... do something with data ...
})
// Note that only one request can be made at a time, or else
// the responses might get confused.

We should use invoke() instead since if several messages are sent ipcRenderer:

// Main
ipcMain.handle('read-file', async (event, path) => {
  if (!pathIsOK(path)) throw new Error('forbidden')
  const buf = await fs.promises.readFile(path)
  return buf
})
// Renderer
const data = await ipcRenderer.invoke('read-file', '/path/to/file')
// ... do something with data ...

FTP: unexpected socket time out reached

Sometimes the following error appears:

Error: Client is closed
at Promise (file:///Users/leo/dev/react-ftp/dist/gui.js:29145:29)
at new Promise ()
at FTPContext.handle (file:///Users/leo/dev/react-ftp/dist/gui.js:29125:16)
at Client.connect (file:///Users/leo/dev/react-ftp/dist/gui.js:28132:25)
at Client.access (file:///Users/leo/dev/react-ftp/dist/gui.js:28229:36)
at Client../src/services/plugins/FsSimpleFtp.ts.Client.login (file:///Users/leo/dev/react-ftp/dist/gui.js:100981:31)
at SimpleFtpApi. (file:///Users/leo/dev/react-ftp/dist/gui.js:101085:55)
at step (file:///Users/leo/dev/react-ftp/dist/gui.js:100927:23)
at Object.next (file:///Users/leo/dev/react-ftp/dist/gui.js:100908:53)
at file:///Users/leo/dev/react-ftp/dist/gui.js:100902:71
Closing reason: Error: Timeout (control socket)
at Socket.socket.once (file:///Users/leo/dev/react-ftp/dist/gui.js:29214:58)
at Object.onceWrapper (events.js:273:13)
at Socket.emit (events.js:182:13)
at Socket._onTimeout (net.js:445:8)
at ontimeout (timers.js:427:11)
at tryOnTimeout (timers.js:289:5)
at listOnTimeout (timers.js:252:5)
at Timer.processTimers (timers.js:212:10)

For example when stopping into a debugger.

A bug has been opened in basic-ftp but it seems to be related to Electron/node.js instead: electron/electron#14915

There is no app icon

On Linux, there is no app icon:

  • AppImage shows the default icon
  • in the title bar, it's the default app icon
  • inside the about messageBox there is no icon

Update about menu label

macOS & Windows & Linux

  • About React-Explorer
  • À propos de React-Explorer

Linux

  • About
  • À propos

macOS: opening a file triggers cache reload and resets scroll position

On macOS:

  1. select a file
  2. press cmd+o to open the file in the finder

This opens the file as expected, but since the last open date of the file has changed, node file watch triggers a change even which in turns reloads the cache and resets the scroll position.

There isn't much that can be done to fix this. Maybe external npm watch modules have more grained support?

Paste function seems to be broken

Depending on the case:

  • files are correctly listed but stays in waiting state
  • no files are listed

In both cases, copy process appears to be stalled.

Changing a tab loses the scrolling's position

If a file is selected, switching to a new tab and switching back may change the scrolling position. The selected element will be visible, but position may have changed.

This won't happen if there is no element selected.

Note that it will only happen if scroll position of the previous tab makes selected element in the new tab not visible.

May be related to this pull request #37

Keyboard nav: active element lost after switching tab

How to reproduce?

  • open a tab with a few files
  • use down key to move selected file
  • cycle to next tab and back
  • use down key

What happens?

First item gets selected

What should happen?

The one after the previously selected one should be selected

Update exit menu label

macOS & Windows & Linux

  • Quit React-Explorer
  • Quitter React-Explorer

Windows

  • Exit
  • Quitter

Linux

  • Quit
  • Quitter

Crash when switching tab with a selected folder

  • open two tabs
  • select a folder in the second tab
  • switch to the first tab

The console shows an exception:

gui.js:63 Uncaught TypeError: Cannot read property 'ino' of null
at gui.js:102
at Array.findIndex ()
at t.getFilePosition (gui.js:102)
at t.updateState (gui.js:102)
at t.updateNodes (gui.js:102)
at gui.js:102
at B (gui.js:42)
at n (gui.js:42)
at l (gui.js:42)
at e.onInvalidate (gui.js:42)

Suggestion: add a "Go" menu

The go (fr: aller) menu should have the following shortcuts entries:

  • backward [existing shortcut] (fr: reculer) [mod+left]
  • forward [existing shortcut] (fr: avancer) [mod+right]
  • enclosing folder [existing shortcut] (fr: dossier parent) [backspace]

Note: for now, do not disable item (for eg. if parent has no effect) as this means we would have to re-generate/render the menu on each directory change because of the way Electron works. So we have to be sure it's safe to run the combo in any case.

Windows: add support for UNC paths

On Windows, it's not possible to browser shared files using Universal Naming Convention (UNC): \\Computer\\Dir.

Adding support for UNC will also allow browsing WSL2 files from ReactExplorer.

Trouble renaming a filename that's too long

It's not possible to rename folder names that are too wide.

How to reproduce?

  • have a filename long enough so that ... is used to crop it
  • attempt to rename it

What happens?
Full filename isn't visible, the ... stay.

What should happen?
The full name should be displayed and not cropped with ....

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.