The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
    ├── FUNDING.yml
    ├── ISSUE_TEMPLATE
    │   ├── bug_report.md
    │   ├── contribute.md
    │   └── feature_request.md
    └── workflows
    │   └── main.yml
├── .gitignore
├── .huskyrc
├── .prettierrc
├── .stylelintrc
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── app
    ├── app.html
    ├── app.icns
    ├── classes
    │   ├── AppUpdate.js
    │   ├── Boot.js
    │   └── Storage.js
    ├── components
    │   ├── Breadcrumb
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   └── index.js
    │   ├── DialogBox
    │   │   ├── components
    │   │   │   ├── Confirm.jsx
    │   │   │   ├── Notification.jsx
    │   │   │   ├── ProgressBar.jsx
    │   │   │   ├── Selection.jsx
    │   │   │   └── TextFieldEdit.jsx
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   ├── Confirm.js
    │   │   │   ├── Notification.js
    │   │   │   ├── ProgressBar.js
    │   │   │   ├── Selection.js
    │   │   │   └── TextFieldEdit.js
    │   ├── LoadingIndicator
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   └── index.js
    │   └── Snackbars
    │   │   ├── components
    │   │       └── SnackbarThemeWrapper.jsx
    │   │   ├── index.jsx
    │   │   └── styles
    │   │       ├── SnackbarThemeWrapper.js
    │   │       └── index.js
    ├── constants
    │   ├── dom.js
    │   ├── env.js
    │   ├── index.js
    │   ├── keymaps.js
    │   ├── meta.js
    │   ├── onboarding.js
    │   ├── paths.js
    │   └── serviceKeys.js
    ├── containers
    │   ├── Alerts
    │   │   ├── actions.js
    │   │   ├── index.jsx
    │   │   └── reducers.js
    │   ├── App
    │   │   ├── Root.jsx
    │   │   ├── actions.js
    │   │   ├── components
    │   │   │   └── Titlebar.jsx
    │   │   ├── index.jsx
    │   │   ├── reducers.js
    │   │   ├── selectors.js
    │   │   └── styles
    │   │   │   ├── Titlebar.js
    │   │   │   └── index.js
    │   ├── AppFeaturesPage
    │   │   ├── Loadable.js
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   └── index.js
    │   ├── AppUpdatePage
    │   │   ├── UpdateAvailable
    │   │   │   ├── Loadable.js
    │   │   │   ├── index.jsx
    │   │   │   └── styles
    │   │   │   │   ├── index.js
    │   │   │   │   └── release-notes.scss
    │   │   └── UpdateProgress
    │   │   │   ├── Loadable.js
    │   │   │   ├── index.jsx
    │   │   │   └── styles
    │   │   │       └── index.js
    │   ├── ErrorBoundary
    │   │   ├── components
    │   │   │   ├── GenerateErrorReport.jsx
    │   │   │   └── GenerateErrorReportBody.jsx
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   ├── GenerateErrorReport.js
    │   │   │   └── index.js
    │   ├── HelpFaqsPage
    │   │   ├── Loadable.js
    │   │   ├── components
    │   │   │   └── HelpPhoneNotRecognized.jsx
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   ├── HelpPhoneNotRecognized.js
    │   │   │   └── index.js
    │   ├── HomePage
    │   │   ├── Loadable.js
    │   │   ├── actions.js
    │   │   ├── components
    │   │   │   ├── FileExplorer.jsx
    │   │   │   ├── FileExplorerBodyRender.jsx
    │   │   │   ├── FileExplorerTableBodyEmptyRender.jsx
    │   │   │   ├── FileExplorerTableBodyGridRender.jsx
    │   │   │   ├── FileExplorerTableBodyGridWrapperRender.jsx
    │   │   │   ├── FileExplorerTableBodyListRender.jsx
    │   │   │   ├── FileExplorerTableBodyListWrapperRender.jsx
    │   │   │   ├── FileExplorerTableBodyRender.jsx
    │   │   │   ├── FileExplorerTableFooterRender.jsx
    │   │   │   ├── FileExplorerTableFooterStatusBarRender.jsx
    │   │   │   ├── FileExplorerTableHeadRender.jsx
    │   │   │   ├── SidebarAreaPaneLists.jsx
    │   │   │   ├── ToolbarAreaPane.jsx
    │   │   │   └── ToolbarBody.jsx
    │   │   ├── index.jsx
    │   │   ├── reducers.js
    │   │   ├── selectors.js
    │   │   └── styles
    │   │   │   ├── FileExplorer.js
    │   │   │   ├── FileExplorerBodyRender.js
    │   │   │   ├── FileExplorerTableBodyEmptyRender.js
    │   │   │   ├── FileExplorerTableBodyGridRender.js
    │   │   │   ├── FileExplorerTableBodyGridWrapperRender.js
    │   │   │   ├── FileExplorerTableBodyListRender.js
    │   │   │   ├── FileExplorerTableBodyRender.js
    │   │   │   ├── FileExplorerTableFooterRender.js
    │   │   │   ├── FileExplorerTableFooterStatusBarRender.js
    │   │   │   ├── FileExplorerTableHeadRender.js
    │   │   │   ├── SidebarAreaPaneLists.js
    │   │   │   ├── ToolbarAreaPane.js
    │   │   │   └── index.js
    │   ├── KeyboardShortcutsPage
    │   │   ├── Loadable.js
    │   │   ├── components
    │   │   │   ├── KbdRender.jsx
    │   │   │   └── KeyboadShortcuts.jsx
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   ├── KeyboadShortcuts.js
    │   │   │   └── index.js
    │   ├── NotFoundPage
    │   │   ├── Loadable.js
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   └── index.scss
    │   ├── Onboarding
    │   │   ├── components
    │   │   │   ├── Features.jsx
    │   │   │   └── WhatsNew.jsx
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   ├── Features.js
    │   │   │   ├── WhatsNew.js
    │   │   │   └── index.js
    │   ├── PrivacyPolicyPage
    │   │   ├── Loadable.js
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   └── index.js
    │   ├── ReportBugsPage
    │   │   ├── Loadable.js
    │   │   ├── index.jsx
    │   │   └── styles
    │   │   │   └── index.js
    │   └── Settings
    │   │   ├── actions.js
    │   │   ├── components
    │   │       ├── SettingsDialog.jsx
    │   │       └── SettingsDialogTabContainer.jsx
    │   │   ├── index.jsx
    │   │   ├── reducers.js
    │   │   ├── selectors.js
    │   │   └── styles
    │   │       └── index.js
    ├── data
    │   └── file-explorer
    │   │   ├── controllers
    │   │       └── FileExplorerController.js
    │   │   ├── data-sources
    │   │       ├── FileExplorerKalamDataSource.js
    │   │       ├── FileExplorerLegacyDataSource.js
    │   │       └── FileExplorerLocalDataSource.js
    │   │   └── repositories
    │   │       └── FileExplorerRepository.js
    ├── enums
    │   ├── appUpdater.js
    │   ├── events.js
    │   ├── index.js
    │   └── mtpError.js
    ├── helpers
    │   ├── binaries.js
    │   ├── bootHelper.js
    │   ├── console.js
    │   ├── createWindows.js
    │   ├── deviceInfo.js
    │   ├── fileOps.js
    │   ├── identifiers.js
    │   ├── logs.js
    │   ├── processBufferOutput.js
    │   ├── reducerPrefixer.js
    │   ├── remoteWindowHelpers.js
    │   ├── settings.js
    │   ├── storageHelper.js
    │   ├── theme.js
    │   ├── titlebarDoubleClick.js
    │   └── windowHelper.js
    ├── index.js
    ├── main.dev.js
    ├── menu.js
    ├── public
    │   └── images
    │   │   ├── FileExplorer
    │   │       ├── buymeacoffee-button.png
    │   │       ├── files-archive.svg
    │   │       ├── folder-blue.svg
    │   │       ├── folder-dark.svg
    │   │       ├── folder-light.svg
    │   │       └── paypal-logo.png
    │   │   ├── bug.svg
    │   │   ├── file-types
    │   │       ├── 7z.svg
    │   │       ├── aac.svg
    │   │       ├── ai.svg
    │   │       ├── archive.svg
    │   │       ├── arj.svg
    │   │       ├── audio.svg
    │   │       ├── avi.svg
    │   │       ├── css.svg
    │   │       ├── csv.svg
    │   │       ├── dbf.svg
    │   │       ├── doc.svg
    │   │       ├── dwg.svg
    │   │       ├── exe.svg
    │   │       ├── fit.svg
    │   │       ├── fla.svg
    │   │       ├── flac.svg
    │   │       ├── gif.svg
    │   │       ├── html.svg
    │   │       ├── iso.svg
    │   │       ├── jpg.svg
    │   │       ├── js.svg
    │   │       ├── json.svg
    │   │       ├── mdf.svg
    │   │       ├── mp2.svg
    │   │       ├── mp3.svg
    │   │       ├── mp4.svg
    │   │       ├── mxf.svg
    │   │       ├── nrg.svg
    │   │       ├── pdf.svg
    │   │       ├── png.svg
    │   │       ├── ppt.svg
    │   │       ├── psd.svg
    │   │       ├── rar.svg
    │   │       ├── rtf.svg
    │   │       ├── svg.svg
    │   │       ├── text.svg
    │   │       ├── tiff.svg
    │   │       ├── txt.svg
    │   │       ├── unknown.svg
    │   │       ├── video.svg
    │   │       ├── wav.svg
    │   │       ├── wma.svg
    │   │       ├── xls.svg
    │   │       ├── xml.svg
    │   │       └── zip.svg
    │   │   ├── help
    │   │       ├── allow-data-access.png
    │   │       ├── charge-only-permission.png
    │   │       ├── full-disk-access-file-picker.jpeg
    │   │       ├── full-disk-access.png
    │   │       ├── google-drive-not-connecting.png
    │   │       ├── macos-directory-access.jpg
    │   │       ├── privacy-restricted-folder-access.png
    │   │       ├── sleep-setting.jpg
    │   │       ├── transfer-media-permission.png
    │   │       ├── usb-notification-charging-via-usb.png
    │   │       └── usb-notification-transferring-media.png
    │   │   ├── no-image.png
    │   │   └── toolbar
    │   │       └── buymeacoffee.png
    ├── routing
    │   └── index.js
    ├── services
    │   ├── analytics
    │   │   ├── googleAnalytics.js
    │   │   ├── index.js
    │   │   └── mixpanelAnalytics.js
    │   ├── ipc-events
    │   │   ├── IpcEventHandler.js
    │   │   └── IpcEventType.js
    │   └── sentry
    │   │   └── index.js
    ├── store
    │   ├── configureStore
    │   │   ├── dev.js
    │   │   ├── index.js
    │   │   └── prod.js
    │   └── reducers
    │   │   ├── index.js
    │   │   └── withReducer.js
    ├── styles
    │   ├── js
    │   │   ├── index.js
    │   │   ├── mixins.js
    │   │   └── variables.js
    │   └── scss
    │   │   ├── app.global.scss
    │   │   ├── base
    │   │       ├── _base.scss
    │   │       ├── _extends.scss
    │   │       ├── _mixins.scss
    │   │       ├── _variables.scss
    │   │       └── mixins
    │   │       │   ├── _align-items.scss
    │   │       │   ├── _animate-link.scss
    │   │       │   ├── _animations.scss
    │   │       │   ├── _backface-visibility.scss
    │   │       │   ├── _background-cover.scss
    │   │       │   ├── _border.scss
    │   │       │   ├── _box-model.scss
    │   │       │   ├── _box-shadow.scss
    │   │       │   ├── _breakpoint.scss
    │   │       │   ├── _clearfix.scss
    │   │       │   ├── _display.scss
    │   │       │   ├── _display_flex.scss
    │   │       │   ├── _flex.scss
    │   │       │   ├── _hide-text.scss
    │   │       │   ├── _horz-vert-center.scss
    │   │       │   ├── _hover-focus.scss
    │   │       │   ├── _inline-block.scss
    │   │       │   ├── _inner-shadow.scss
    │   │       │   ├── _keyframes.scss
    │   │       │   ├── _linear-gradient-angle.scss
    │   │       │   ├── _linear-gradient.scss
    │   │       │   ├── _margin-auto.scss
    │   │       │   ├── _mediumFont.scss
    │   │       │   ├── _min-breakpoint.scss
    │   │       │   ├── _opacity.scss
    │   │       │   ├── _placeholder.scss
    │   │       │   ├── _rem.scss
    │   │       │   ├── _replace-text.scss
    │   │       │   ├── _retina.scss
    │   │       │   ├── _rounded-corners.scss
    │   │       │   ├── _single-transform.scss
    │   │       │   ├── _text-shadow.scss
    │   │       │   ├── _transform.scss
    │   │       │   ├── _transitions.scss
    │   │       │   ├── _translate.scss
    │   │       │   └── _triangles.scss
    │   │   └── themes
    │   │       ├── fonts.scss
    │   │       └── reset.scss
    ├── templates
    │   ├── appFeaturesPage.js
    │   ├── fileExplorer.js
    │   ├── generateErrorReport.js
    │   ├── helpFaqsPage.js
    │   ├── keyboardShortcutsPage.js
    │   ├── loadProfileError.js
    │   ├── menu.js
    │   ├── privacyPolicyPage.js
    │   └── socialMediaShareBtns.js
    ├── utils
    │   ├── checkIf.js
    │   ├── date.js
    │   ├── errors.js
    │   ├── eventHandling.js
    │   ├── files.js
    │   ├── funcs.js
    │   ├── getPlatform.js
    │   ├── gzip.js
    │   ├── imgsrc.js
    │   ├── isGoogleAndroidFileTransferActive.js
    │   ├── isOnline.js
    │   ├── isPackaged.js
    │   ├── log.js
    │   ├── pkginfo.js
    │   ├── process.js
    │   ├── styleResets.js
    │   ├── styles.js
    │   └── url.js
    └── vendors
    │   └── pretty-file-icons
    │       ├── LICENSE
    │       ├── README.md
    │       ├── index.js
    │       ├── index.json
    │       └── package.json
├── babel.config.js
├── blobs
    ├── binaries
    │   ├── .gitkeep
    │   └── libusb_1.0.22_el_capitan_darwin_amd64.tar.gz
    └── images
    │   ├── file-explorer-bluebg.jpg
    │   ├── file-explorer.png
    │   ├── file-transfer-bluebg.jpg
    │   ├── file-transfer-large.png
    │   └── file-transfer.png
├── build
    ├── entitlements.mac.plist
    ├── icon.icns
    ├── icon.ico
    ├── icon.png
    ├── icons
    │   ├── 1024x1024.png
    │   ├── 128x128.png
    │   ├── 16x16.png
    │   ├── 256x256.png
    │   ├── 32x32.png
    │   ├── 512x512.png
    │   └── 64x64.png
    ├── mac
    │   └── bin
    │   │   ├── amd64
    │   │       ├── kalam.dylib
    │   │       ├── kalam.h
    │   │       ├── kalam_debug_report
    │   │       └── libusb.dylib
    │   │   ├── arm64
    │   │       ├── kalam.dylib
    │   │       ├── kalam.h
    │   │       ├── kalam_debug_report
    │   │       └── libusb.dylib
    │   │   ├── medieval
    │   │       └── amd64
    │   │       │   ├── kalam.dylib
    │   │       │   ├── kalam.h
    │   │       │   ├── kalam_debug_report
    │   │       │   └── libusb.dylib
    │   │   └── mtp-cli
    └── sample.entitlements.mas.plist
├── codemagic.yaml
├── config
    ├── dev-app-update.yml
    └── env
    │   ├── env.dev.js
    │   ├── env.prod.js
    │   └── index.js
├── docs-sources
    ├── images
    │   ├── file-explorer.png
    │   └── file-transfer.png
    ├── index.js
    ├── styles
    │   ├── base
    │   │   ├── _base.scss
    │   │   └── _themes.scss
    │   └── global.scss
    ├── templates
    │   ├── index.html
    │   └── privacy.html
    ├── utils
    │   ├── consts.js
    │   └── funcs.js
    └── webpack
    │   ├── webpack.config.base.js
    │   ├── webpack.config.dev.js
    │   └── webpack.config.prod.js
├── docs
    ├── CNAME
    ├── _config.yml
    ├── bundle
    │   ├── file-explorer.1b1a659da61529904113.png
    │   ├── file-transfer.e01ae86967cd5e83a375.png
    │   ├── index.2a3c7308644dc6b26b7d.css
    │   └── index.6845514fce43dda32e49.js
    ├── favicon.ico
    ├── google25c4a4597b2b27f3.html
    ├── index.html
    ├── privacy.html
    ├── robots.txt
    └── sitemap.xml
├── electron-builder-config.js
├── ffi
    └── kalam
    │   ├── native
    │       ├── .gitignore
    │       ├── README.md
    │       ├── go.mod
    │       ├── go.sum
    │       ├── helpers.go
    │       ├── kalam.go
    │       ├── kalam_debug_report
    │       │   └── main.go
    │       ├── scripts
    │       │   └── build.mjs
    │       ├── send_to_js
    │       │   ├── constants.go
    │       │   ├── enums.go
    │       │   ├── errors.go
    │       │   ├── helpers.go
    │       │   ├── main.go
    │       │   └── structs.go
    │       ├── structs.go
    │       └── utils.go
    │   └── src
    │       └── Kalam.js
├── internals
    └── scripts
    │   ├── AfterPack.js
    │   ├── CheckBuildExist.js
    │   ├── CheckNodeEnv.js
    │   ├── CheckPortInUse.js
    │   ├── CheckYarn.js
    │   ├── Notarize.js
    │   ├── OptionalDepsInstall.js
    │   ├── preinstall.sh
    │   └── semver.js
├── lint-staged.config.js
├── package.json
├── sample.env
├── sample.sentry.properties
├── scripts
    └── cicd
    │   ├── axios.mjs
    │   ├── base.mjs
    │   ├── codemagic-publish-builds.mjs
    │   ├── codemagic-start-mac-intel-x64-vm.mjs
    │   └── constants.mjs
├── sentry-symbols.js
├── webpack
    ├── config.base.js
    ├── config.eslint.js
    ├── config.main.prod.babel.js
    ├── config.renderer.dev.babel.js
    ├── config.renderer.dev.dll.babel.js
    └── config.renderer.prod.babel.js
└── yarn.lock


/.eslintignore:
--------------------------------------------------------------------------------
 1 | # Logs
 2 | logs
 3 | *.log
 4 | 
 5 | # Runtime data
 6 | pids
 7 | *.pid
 8 | *.seed
 9 | 
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 | 
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 | 
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 | 
19 | # node-waf configuration
20 | .lock-wscript
21 | 
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 | .eslintcache
25 | 
26 | # Dependency directory
27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
28 | node_modules
29 | 
30 | # OSX
31 | .DS_Store
32 | 
33 | # flow-typed
34 | flow-typed/npm/*
35 | !flow-typed/npm/module_vx.x.x.js
36 | 
37 | # App packaged
38 | release
39 | app/main.prod.js
40 | app/main.prod.js.map
41 | app/renderer.prod.js
42 | app/renderer.prod.js.map
43 | app/style.css
44 | app/style.css.map
45 | dist
46 | dll
47 | main.js
48 | main.js.map
49 | app/vendors
50 | 
51 | 
52 | .idea
53 | npm-debug.log.*
54 | __snapshots__
55 | 
56 | # Package.json
57 | package.json
58 | .travis.yml
59 | 
60 | .env*
61 | .idea
62 | vendors
63 | build
64 | docs
65 | .vscode
66 | .github
67 | app/dll
68 | .prettierrc
69 | .stylelintrc
70 | .eslintrc.json
71 | 
72 | 
73 | package-lock.json
74 | sentry.properties
75 | 
76 | app/certs/*.pem
77 | certs/*
78 | todo.txt
79 | *yarn-error.log
80 | eslint-common-rules.txt
81 | 
82 | build/entitlements.mas.plist
83 | *embedded.provisionprofile
84 | extras/*
85 | mtp-mock-files/*
86 | resources
87 | tmp/*
88 | *.prod.js
89 | *.js.map
90 | *.js.LICENSE.txt
91 | *.prod.js.LICENSE.txt
92 | 


--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 | 


--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | custom:
2 | - https://paypal.me/ganeshrvel
3 | - https://buymeacoffee.com/ganeshrvel
4 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
 1 | ---
 2 | name: Bug report
 3 | about: Create a report to help us improve
 4 | labels: 'bug'
 5 | 
 6 | ---
 7 | 
 8 | **Prerequisites**
 9 | 
10 | - [ ] Have you reviewed the steps in the following link to see if they address your issue? 
11 |   - https://github.com/ganeshrvel/openmtp/issues/276
12 | 
13 | **Describe the bug**
14 | A clear and concise description of what the bug is.
15 | 
16 | 
17 | **Attachments**
18 | Include if relevant,
19 | 1. Open your Terminal and run the following code:
20 | ```shell
21 | zip -r -X ~/Desktop/OpenMTP-log.zip "$HOME/Library/Application Support/io.ganeshrvel.openmtp/logs/"
22 | ```
23 | 2. Attach the file *OpenMTP-log.zip* found in your Desktop folder here.
24 | 
25 | Or
26 | 
27 | 1. Open the App,
28 | 2. Click on Help > Report Bugs.
29 | 3. Generate and send us the bugs report.
30 | 
31 | **Screenshots**
32 | If applicable, add screenshots to help explain your problem.
33 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/contribute.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Contribute
3 | about: Open a new issue and contribute to the app.
4 | ---
5 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: You want something added to the app or code.
4 | labels: 'enhancement'
5 | ---
6 | 


--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
 1 | name: CI
 2 | 
 3 | on:
 4 |   push:
 5 |     branches: [ master ]
 6 |   pull_request:
 7 |     branches: [ master ]
 8 | 
 9 | jobs:
10 |   build:
11 |     runs-on: macOS-11.00
12 |     steps:
13 |       - name: Setup build environment
14 |         uses: actions/setup-node@v1
15 |         with:
16 |           node-version: '16.x'
17 |       - run: npm install -g cross-env create-dmg
18 |       - name: Cloning Git repository
19 |         uses: actions/checkout@v1
20 |       - name: Attempt to build OpenMTP
21 |         run: |
22 |           yarn
23 |           yarn build
24 |       - name: Attempt to generate unsigned macOS app
25 |         run: |
26 |           export CSC_IDENTITY_AUTO_DISCOVERY=false
27 |           yarn package-mac-without-notarize 2>&1 || true
28 |       - name: Check if macOS app was generated
29 |         run: test -e dist/mac/OpenMTP.app
30 |       - name: Attempt to create disk image for generated macOS app
31 |         run: |
32 |           mkdir dist/dmg
33 |           create-dmg dist/mac/OpenMTP.app dist/dmg 2>&1 || true
34 |           shasum dist/dmg/* >> dist/dmg/CHECKSUM_SHA256.txt
35 |       - name: Upload disk image and checksum as artifact
36 |         uses: actions/upload-artifact@v1.0.0
37 |         with:
38 |           name: 'Disk Image'
39 |           path: dist/dmg/
40 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | # Logs
 2 | logs
 3 | *.log
 4 | 
 5 | # Runtime data
 6 | pids
 7 | *.pid
 8 | *.seed
 9 | 
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 | 
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 | 
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 | 
19 | # node-waf configuration
20 | .lock-wscript
21 | 
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 | .eslintcache
25 | 
26 | # Dependency directory
27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
28 | node_modules/
29 | app/node_modules
30 | 
31 | # OSX
32 | .DS_Store
33 | 
34 | # flow-typed
35 | flow-typed/npm/*
36 | !flow-typed/npm/module_vx.x.x.js
37 | 
38 | # App packaged
39 | release
40 | app/main.prod.js
41 | app/main.prod.js.map
42 | app/renderer.prod.js
43 | app/renderer.prod.js.map
44 | app/style.css
45 | app/style.css.map
46 | dist
47 | dll
48 | main.js
49 | main.js.map
50 | 
51 | .idea
52 | npm-debug.log.*
53 | package-lock.json
54 | .env*
55 | sentry.properties
56 | 
57 | app/certs/*.pem
58 | certs/*
59 | todo.txt
60 | *yarn-error.log
61 | eslint-common-rules.txt
62 | 
63 | build/entitlements.mas.plist
64 | *embedded.provisionprofile
65 | extras/*
66 | mtp-mock-files/*
67 | resources
68 | tmp/*
69 | *.prod.js
70 | *.js.map
71 | *.js.LICENSE.txt
72 | *.prod.js.LICENSE.txt
73 | 


--------------------------------------------------------------------------------
/.huskyrc:
--------------------------------------------------------------------------------
1 | {
2 |   "hooks": {
3 | 	"pre-commit": "lint-staged"
4 |   }
5 | }
6 | 


--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
 1 | {
 2 |   "overrides": [
 3 |     {
 4 |       "files": [".prettierrc", ".babelrc", ".eslintrc", ".stylelintrc"],
 5 |       "options": {
 6 |         "parser": "json"
 7 |       }
 8 |     }
 9 |   ],
10 |   "singleQuote": true
11 | }
12 | 


--------------------------------------------------------------------------------
/.stylelintrc:
--------------------------------------------------------------------------------
 1 | {
 2 |   "extends": ["stylelint-config-standard", "stylelint-config-prettier"],
 3 |   "rules": {
 4 |     "color-function-notation": null,
 5 |     "value-no-vendor-prefix": null,
 6 |     "property-no-vendor-prefix": null,
 7 |     "font-family-name-quotes": null,
 8 |     "rule-empty-line-before": null,
 9 |     "at-rule-no-vendor-prefix": null,
10 |     "shorthand-property-no-redundant-values": null,
11 |     "selector-class-pattern": null,
12 |     "annotation-no-unknown": null,
13 |     "value-keyword-case": null,
14 |     "function-no-unknown": null,
15 |     "selector-no-vendor-prefix": null,
16 |     "media-feature-name-no-vendor-prefix": null,
17 |     "alpha-value-notation": null,
18 |     "at-rule-no-unknown": null,
19 |     "import-notation": null,
20 |     "no-descending-specificity": null
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
 1 | # Contributing to OpenMTP
 2 | 
 3 | Thank you for your interest in contributing to OpenMTP!
 4 | 
 5 | ### How to Contribute
 6 | - Create a new issue [here](https://github.com/ganeshrvel/openmtp/issues/new "here").
 7 | - Assign yourself as the "Assignees".
 8 | - Fork the repo and create your branch from the **master** (important!).
 9 | - Make your changes.
10 | - Ensure that the changes pass linting.
11 | - Update the documentation if needed.
12 | - Add short, meaningful commit message that describes the change you made to the code.
13 | - Append the issue URL in the commit message.
14 | - Issue a pull request to the **development** branch.
15 | - Add a reviewer.
16 | 
17 | When you submit code changes, your submissions are understood to be under the same [MIT License](https://github.com/ganeshrvel/openmtp/blob/master/LICENSE "MIT License") that covers the project. Feel free to contact the maintainers if that's a concern.
18 | 


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | The MIT License (MIT)
 2 | 
 3 | Copyright (c) 2010-present Ganesh Rathinavel
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 
23 | 


--------------------------------------------------------------------------------
/app/app.html:
--------------------------------------------------------------------------------
 1 | <!DOCTYPE html>
 2 | <html lang="en">
 3 | <head>
 4 |   <meta charset="utf-8">
 5 |   <meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" />
 6 |   <title>OpenMTP | Android File Transfer for macOS</title>
 7 |   <script>
 8 |     (() => {
 9 |       if (typeof process === "object" && typeof process.env === "object" && typeof process.env.NODE_ENV === "undefined") {
10 |         process.env.NODE_ENV = "production";
11 |       }
12 | 
13 |       if (
14 |         typeof process !== "object" ||
15 |         (typeof process === "object" && !process.env.START_HOT)
16 |       ) {
17 |         const link = document.createElement("link");
18 |         link.rel = "stylesheet";
19 |         link.href = "./dist/style.css";
20 |         // HACK: Writing the script path should be done with webpack
21 |         document.getElementsByTagName("head")[0].appendChild(link);
22 |       }
23 |     })();
24 |   </script>
25 | </head>
26 | <body>
27 | <div id="root"></div>
28 | <script>
29 |   if (typeof process === "object") {
30 |     const scripts = [];
31 |     let PORT;
32 | 
33 |     if (process.env.NODE_ENV === "development") {
34 |       // Dynamically insert the DLL script in development env in the
35 |       // renderer process
36 |       scripts.push("../dll/renderer.dev.dll.js");
37 | 
38 |       PORT = require("../config/env").PORT;
39 |     }
40 |     if (process.env.START_HOT) {
41 |       // Dynamically insert the bundled app script in the renderer process
42 |       scripts.push(`http://localhost:${PORT}/dist/renderer.dev.js`);
43 |     } else {
44 |       scripts.push("./dist/renderer.prod.js");
45 |     }
46 | 
47 |     if (scripts.length) {
48 |       document.write(
49 |         scripts
50 |           .map(script => `<script defer src="${script}"><\/script>`)
51 |           .join("")
52 |       );
53 |     }
54 |   }
55 | </script>
56 | </body>
57 | </html>
58 | 


--------------------------------------------------------------------------------
/app/app.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/app.icns


--------------------------------------------------------------------------------
/app/components/Breadcrumb/styles/index.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => {
 4 |   return {
 5 |     root: {
 6 |       width: `100%`,
 7 |       height: `100%`,
 8 |     },
 9 | 
10 |     rootBreadcrumbs: {
11 |       width: `100%`,
12 |       height: `100%`,
13 |     },
14 | 
15 |     breadcrumb: {
16 |       padding: '10px 15px',
17 |       backgroundColor: theme.palette.background.paper,
18 |       display: 'flex',
19 |       alignItems: 'center',
20 |       ...mixins({ theme }).resetUl,
21 |     },
22 | 
23 |     breadcrumbLi: {
24 |       display: 'inline-block',
25 |       padding: '0 2px 4px 2px',
26 |       overflow: 'hidden',
27 |       fontSize: 14,
28 |       maxWidth: 59,
29 |       whiteSpace: 'nowrap',
30 |       textOverflow: 'ellipsis',
31 |     },
32 | 
33 |     breadcrumbLiA: {
34 |       cursor: `pointer`,
35 |       color: theme.palette.secondary.main,
36 |       textDecoration: 'none',
37 |       [`&.bold`]: {
38 |         fontWeight: `bold`,
39 |       },
40 |     },
41 |     breadcrumbSeperator: {
42 |       fontSize: 18,
43 |     },
44 |   };
45 | };
46 | 


--------------------------------------------------------------------------------
/app/components/DialogBox/index.jsx:
--------------------------------------------------------------------------------
1 | export { default as Notification } from './components/Notification';
2 | export { default as Confirm } from './components/Confirm';
3 | export { default as TextFieldEdit } from './components/TextFieldEdit';
4 | export { default as Selection } from './components/Selection';
5 | export { default as ProgressBar } from './components/ProgressBar';
6 | 


--------------------------------------------------------------------------------
/app/components/DialogBox/styles/Confirm.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   margin: {},
 5 |   root: {},
 6 |   btnPositive: {
 7 |     ...mixins({ theme }).btnPositive,
 8 |   },
 9 |   btnNegative: {
10 |     ...mixins({ theme }).btnNegative,
11 |   },
12 | });
13 | 


--------------------------------------------------------------------------------
/app/components/DialogBox/styles/Notification.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   margin: {},
 5 |   root: {},
 6 |   btnPositive: {
 7 |     ...mixins({ theme }).btnPositive,
 8 |   },
 9 |   btnNegative: {
10 |     ...mixins({ theme }).btnNegative,
11 |   },
12 | });
13 | 


--------------------------------------------------------------------------------
/app/components/DialogBox/styles/ProgressBar.js:
--------------------------------------------------------------------------------
 1 | export const styles = (_) => ({
 2 |   root: {
 3 |     flexGrow: 1,
 4 |   },
 5 |   dialogFixMultipleProgressPadding: {
 6 |     marginTop: 35,
 7 |   },
 8 |   dialogContentTextTop: {
 9 |     marginBottom: 10,
10 |     fontSize: 14,
11 |   },
12 |   dialogContentTextBottom: {
13 |     marginTop: 10,
14 |     fontSize: 14,
15 |   },
16 |   dialogTitleInnerWrapper: {
17 |     alignItems: `center`,
18 |   },
19 |   helpText: {
20 |     float: `right`,
21 |   },
22 |   titleText: {
23 |     float: `left`,
24 |     fontSize: 17,
25 |   },
26 |   bottomText: {
27 |     fontSize: 10,
28 |     fontWeight: 400,
29 |     padding: '0px 0 15px 0',
30 |   },
31 |   childrenWrapper: {
32 |     padding: '0px 0 5px 0',
33 |   },
34 | });
35 | 


--------------------------------------------------------------------------------
/app/components/DialogBox/styles/Selection.js:
--------------------------------------------------------------------------------
 1 | export const styles = (theme) => ({
 2 |   root: {},
 3 |   selectedAvatar: {
 4 |     background: theme.palette.secondary.main,
 5 |   },
 6 |   selectedIcon: {
 7 |     color: '#fff',
 8 |   },
 9 | });
10 | 


--------------------------------------------------------------------------------
/app/components/DialogBox/styles/TextFieldEdit.js:
--------------------------------------------------------------------------------
 1 | import styled from 'styled-components';
 2 | import TextField from '@material-ui/core/TextField';
 3 | import { mixins } from '../../../styles/js';
 4 | 
 5 | export const styles = (theme) => ({
 6 |   root: {},
 7 |   dialogContentText: {
 8 |     marginBottom: 10,
 9 |     wordBreak: `break-all`,
10 |   },
11 |   bodyText: {
12 |     display: 'block',
13 |   },
14 |   secondaryText: {
15 |     marginBottom: 20,
16 |     display: 'block',
17 |   },
18 |   btnPositive: {
19 |     ...mixins({ theme }).btnPositive,
20 |   },
21 |   btnNegative: {
22 |     ...mixins({ theme }).btnNegative,
23 |   },
24 |   textFieldRoot: {
25 |     '& .MuiFormLabel-root.Mui-error.Mui-focused': {
26 |       color: '#f44336',
27 |     },
28 |     '& .MuiFormLabel-root.Mui-focused': {
29 |       color: 'unset',
30 |     },
31 |   },
32 | });
33 | 
34 | export const StyledTextField = styled(TextField)`
35 |   /* hover (double-ampersand needed for specificity reasons. */
36 |   && .MuiInput-underline:hover:before {
37 |     border-bottom: 1px solid rgba(0, 0, 0);
38 |   }
39 |   /* focused */
40 |   .MuiInput-underline:after {
41 |     border-bottom: 1px solid rgba(0, 0, 0, 0.87);
42 |   }
43 |   /* focused */
44 |   .MuiInputLabel-root.MuiInput-focused {
45 |     color: #000;
46 |   }
47 | `;
48 | 


--------------------------------------------------------------------------------
/app/components/LoadingIndicator/index.jsx:
--------------------------------------------------------------------------------
 1 | import React from 'react';
 2 | import { withStyles } from '@material-ui/core/styles';
 3 | import CircularProgress from '@material-ui/core/CircularProgress';
 4 | import { styles } from './styles';
 5 | 
 6 | function LoadingIndicator(props) {
 7 |   const { classes: styles } = props;
 8 | 
 9 |   return (
10 |     <div>
11 |       <CircularProgress
12 |         color="secondary"
13 |         className={styles.progress}
14 |         size={50}
15 |       />
16 |     </div>
17 |   );
18 | }
19 | 
20 | export default withStyles(styles)(LoadingIndicator);
21 | 


--------------------------------------------------------------------------------
/app/components/LoadingIndicator/styles/index.js:
--------------------------------------------------------------------------------
1 | export const styles = (_) => ({
2 |   root: {},
3 |   progress: {
4 |     position: `absolute`,
5 |     top: `50%`,
6 |     left: `50%`,
7 |   },
8 | });
9 | 


--------------------------------------------------------------------------------
/app/components/Snackbars/components/SnackbarThemeWrapper.jsx:
--------------------------------------------------------------------------------
 1 | import React from 'react';
 2 | import classNames from 'classnames';
 3 | import CheckCircleIcon from '@material-ui/icons/CheckCircle';
 4 | import ErrorIcon from '@material-ui/icons/Error';
 5 | import InfoIcon from '@material-ui/icons/Info';
 6 | import Button from '@material-ui/core/Button';
 7 | import SnackbarContent from '@material-ui/core/SnackbarContent';
 8 | import WarningIcon from '@material-ui/icons/Warning';
 9 | import { withStyles } from '@material-ui/core/styles';
10 | import { styles } from '../styles/SnackbarThemeWrapper';
11 | 
12 | const variantIcon = {
13 |   success: CheckCircleIcon,
14 |   warning: WarningIcon,
15 |   error: ErrorIcon,
16 |   info: InfoIcon,
17 | };
18 | 
19 | function SnackbarThemeWrapper(props) {
20 |   const { classes: styles, message, onClose, variant, ...other } = props;
21 |   const Icon = variantIcon[variant];
22 | 
23 |   return (
24 |     <SnackbarContent
25 |       onClick={onClose}
26 |       className={classNames(styles[variant], styles.root)}
27 |       aria-describedby="client-snackbar"
28 |       message={
29 |         <span id="client-snackbar" className={styles.message}>
30 |           <Icon className={classNames(styles.icon, styles.iconVariant)} />
31 |           {message}
32 |         </span>
33 |       }
34 |       action={[
35 |         <Button
36 |           key={1}
37 |           onClick={onClose}
38 |           color="primary"
39 |           className={styles.closeBtn}
40 |         >
41 |           Close
42 |         </Button>,
43 |       ]}
44 |       {...other}
45 |     />
46 |   );
47 | }
48 | 
49 | export default withStyles(styles)(SnackbarThemeWrapper);
50 | 


--------------------------------------------------------------------------------
/app/components/Snackbars/index.jsx:
--------------------------------------------------------------------------------
 1 | import React, { PureComponent } from 'react';
 2 | import Snackbar from '@material-ui/core/Snackbar';
 3 | import { withStyles } from '@material-ui/core/styles';
 4 | import SnackbarThemeWrapper from './components/SnackbarThemeWrapper';
 5 | import { styles } from './styles';
 6 | 
 7 | class Snackbars extends PureComponent {
 8 |   constructor(props) {
 9 |     super(props);
10 |     this.snackbarOpen = false;
11 |   }
12 | 
13 |   componentWillMount() {
14 |     this.fireSnackbar();
15 |   }
16 | 
17 |   fireSnackbar = () => {
18 |     this.snackbarOpen = true;
19 |   };
20 | 
21 |   _handleClose = (event, reason) => {
22 |     const { OnSnackBarsCloseAlerts } = this.props;
23 | 
24 |     if (reason === 'clickaway') {
25 |       return;
26 |     }
27 | 
28 |     this.snackbarOpen = false;
29 |     OnSnackBarsCloseAlerts();
30 |   };
31 | 
32 |   render() {
33 |     const { classes: styles, message, variant, autoHideDuration } = this.props;
34 | 
35 |     return (
36 |       <Snackbar
37 |         className={styles.root}
38 |         anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
39 |         open={this.snackbarOpen}
40 |         autoHideDuration={autoHideDuration}
41 |         onClose={this._handleClose}
42 |       >
43 |         <SnackbarThemeWrapper
44 |           onClose={this._handleClose}
45 |           variant={variant}
46 |           message={message}
47 |         />
48 |       </Snackbar>
49 |     );
50 |   }
51 | }
52 | 
53 | export default withStyles(styles)(Snackbars);
54 | 


--------------------------------------------------------------------------------
/app/components/Snackbars/styles/SnackbarThemeWrapper.js:
--------------------------------------------------------------------------------
 1 | import green from '@material-ui/core/colors/green';
 2 | import amber from '@material-ui/core/colors/amber';
 3 | 
 4 | export const styles = (theme) => ({
 5 |   success: {
 6 |     backgroundColor: green[600],
 7 |   },
 8 |   error: {
 9 |     backgroundColor: theme.palette.snackbar.error,
10 |   },
11 |   info: {
12 |     backgroundColor: theme.palette.primary.dark,
13 |   },
14 |   warning: {
15 |     backgroundColor: amber[700],
16 |   },
17 |   icon: {
18 |     fontSize: 25,
19 |     color: '#fff',
20 |   },
21 |   closeBtn: {
22 |     color: '#fff',
23 |   },
24 |   iconVariant: {
25 |     opacity: 0.9,
26 |     marginRight: 10,
27 |   },
28 |   message: {
29 |     display: 'flex',
30 |     alignItems: 'center',
31 |     color: '#fff',
32 |     fontWeight: 500,
33 |   },
34 |   root: {
35 |     minWidth: 288,
36 |     maxWidth: 568,
37 |     minHeight: 60,
38 |     borderRadius: 15,
39 |     flexGrow: `unset`,
40 |     cursor: `pointer`,
41 |   },
42 | });
43 | 


--------------------------------------------------------------------------------
/app/components/Snackbars/styles/index.js:
--------------------------------------------------------------------------------
 1 | export const styles = (_) => ({
 2 |   margin: {
 3 |     margin: 10,
 4 |   },
 5 |   root: {
 6 |     top: 10,
 7 |     right: 15,
 8 |     left: `unset`,
 9 |   },
10 | });
11 | 


--------------------------------------------------------------------------------
/app/constants/dom.js:
--------------------------------------------------------------------------------
1 | export const APP_TITLEBAR_DOM_ID = `app-main-titlebar`;
2 | 
3 | export const FILE_EXPLORER_BODY_WRAPPER_ID = `file-explorer-body-wrapper`;
4 | 


--------------------------------------------------------------------------------
/app/constants/env.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Constants
 3 |  * Note: Don't import log helper file from utils here
 4 |  */
 5 | 
 6 | const isDev = process.env.NODE_ENV !== 'production';
 7 | const isProd = process.env.NODE_ENV === 'production';
 8 | const isDebug = process.env.DEBUG_PROD === 'true';
 9 | 
10 | const config = {
11 |   dev: {
12 |     reportToSenty: false,
13 |     enableGoogleAnalytics: false,
14 |     enableMixpanelAnalytics: false,
15 |     disableReactWarnings: true,
16 |     allowDevelopmentEnvironment: true,
17 |   },
18 |   prod: {
19 |     reportToSenty: true,
20 |     enableGoogleAnalytics: true,
21 |     enableMixpanelAnalytics: true,
22 |     disableReactWarnings: false,
23 |     allowDevelopmentEnvironment: false,
24 |   },
25 |   debug: {
26 |     reportToSenty: true,
27 |     enableGoogleAnalytics: true,
28 |     enableMixPanelAnalytics: true,
29 |     disableReactWarnings: false,
30 |     allowDevelopmentEnvironment: true,
31 |   },
32 | };
33 | 
34 | let _env = 'dev';
35 | 
36 | if (isProd) {
37 |   _env = 'prod';
38 | } else if (isDebug) {
39 |   _env = 'debug';
40 | }
41 | 
42 | module.exports.ENV_FLAVOR = config[_env];
43 | 
44 | module.exports.IS_DEV = isDev;
45 | 
46 | module.exports.IS_PROD = isProd;
47 | 
48 | module.exports.DEBUG_PROD = isDebug;
49 | 
50 | module.exports.IS_RENDERER = process && process.type === 'renderer';
51 | 


--------------------------------------------------------------------------------
/app/constants/meta.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Constants
 3 |  * Note: Don't import log helper file from utils here
 4 |  */
 5 | 
 6 | import { pkginfo } from '../utils/pkginfo';
 7 | 
 8 | const {
 9 |   productName,
10 |   description,
11 |   name,
12 |   author,
13 |   version,
14 |   repository,
15 |   homepage,
16 |   bugs,
17 | } = pkginfo;
18 | 
19 | export const APP_BUNDLE_ID = 'io.ganeshrvel.openmtp';
20 | 
21 | export const APP_NAME = `${productName}`;
22 | 
23 | export const APP_VERSION = `${version}`;
24 | 
25 | export const AUTHOR_EMAIL = author?.email ?? null;
26 | 
27 | export const AUTHOR_NAME = author?.name ?? null;
28 | 
29 | export const APP_DESC = `${description}`;
30 | 
31 | export const APP_TITLE = `${APP_DESC}`;
32 | 
33 | export const APP_IDENTIFIER = `${name}`;
34 | 
35 | export const APP_GITHUB_URL = repository?.url
36 |   ? repository.url.replace(/^git\+|\.git/g, '')
37 |   : null;
38 | 
39 | export const APP_GITHUB_RELEASES_URL = `${APP_GITHUB_URL}/releases`;
40 | 
41 | export const APP_GITHUB_ISSUES_URL = bugs?.url ?? null;
42 | 
43 | export const APP_WEBSITE = `${homepage}`;
44 | 


--------------------------------------------------------------------------------
/app/constants/onboarding.js:
--------------------------------------------------------------------------------
1 | // most recently used version number to show the onboarding screen
2 | // search keywords: new, next, update, onboarding
3 | export const latestUpdatePushVersion = '3.2.20';
4 | 


--------------------------------------------------------------------------------
/app/constants/serviceKeys.js:
--------------------------------------------------------------------------------
1 | export const SERVICE_KEYS = {
2 |   sentryDsn: `https://1f60d05960cc4c10a744bebd19bc2814@o410539.ingest.sentry.io/5544425`,
3 |   googleAnalytics: `UA-131227413-1`,
4 |   mixpanelAnalytics: `e2ae6803122e622822a5fbf32ff0e5ae`,
5 | };
6 | 


--------------------------------------------------------------------------------
/app/containers/Alerts/actions.js:
--------------------------------------------------------------------------------
 1 | import prefixer from '../../helpers/reducerPrefixer';
 2 | 
 3 | const prefix = '@@Alerts';
 4 | const actionTypesList = ['THROW_ALERT', 'CLEAR_ALERT'];
 5 | 
 6 | export const actionTypes = prefixer(prefix, actionTypesList);
 7 | 
 8 | export function throwAlert(data) {
 9 |   return {
10 |     type: actionTypes.THROW_ALERT,
11 |     payload: {
12 |       ...data,
13 |     },
14 |   };
15 | }
16 | 
17 | export function clearAlert() {
18 |   return {
19 |     type: actionTypes.CLEAR_ALERT,
20 |   };
21 | }
22 | 


--------------------------------------------------------------------------------
/app/containers/Alerts/index.jsx:
--------------------------------------------------------------------------------
 1 | import React, { Component } from 'react';
 2 | import { connect } from 'react-redux';
 3 | import { bindActionCreators } from 'redux';
 4 | import { withReducer } from '../../store/reducers/withReducer';
 5 | import reducers from './reducers';
 6 | import { clearAlert } from './actions';
 7 | import Snackbars from '../../components/Snackbars';
 8 | 
 9 | class Alerts extends Component {
10 |   _handleClose = () => {
11 |     const { actionCreateClearAlert } = this.props;
12 | 
13 |     actionCreateClearAlert();
14 |   };
15 | 
16 |   render() {
17 |     const { Alerts } = this.props;
18 |     const { message, variant, autoHideDuration } = Alerts;
19 | 
20 |     return (
21 |       message && (
22 |         <Snackbars
23 |           OnSnackBarsCloseAlerts={() => this._handleClose()}
24 |           message={message}
25 |           variant={variant}
26 |           autoHideDuration={autoHideDuration}
27 |         />
28 |       )
29 |     );
30 |   }
31 | }
32 | 
33 | const mapDispatchToProps = (dispatch, __) =>
34 |   bindActionCreators(
35 |     {
36 |       actionCreateClearAlert: () => (_, __) => {
37 |         dispatch(clearAlert());
38 |       },
39 |     },
40 |     dispatch
41 |   );
42 | 
43 | const mapStateToProps = (state, __) => {
44 |   return {
45 |     Alerts: state.Alerts,
46 |   };
47 | };
48 | 
49 | export default withReducer(
50 |   'Alerts',
51 |   reducers
52 | )(connect(mapStateToProps, mapDispatchToProps)(Alerts));
53 | 


--------------------------------------------------------------------------------
/app/containers/Alerts/reducers.js:
--------------------------------------------------------------------------------
 1 | import { actionTypes } from './actions';
 2 | 
 3 | export const initialState = {
 4 |   message: null,
 5 |   autoHideDuration: 2500, // in ms
 6 |   variant: `error`,
 7 | };
 8 | 
 9 | export default function Alerts(state = initialState, action) {
10 |   const { type, payload } = action;
11 | 
12 |   switch (type) {
13 |     case actionTypes.THROW_ALERT:
14 |       return {
15 |         ...state,
16 |         ...payload,
17 |       };
18 |     case actionTypes.CLEAR_ALERT:
19 |       return {
20 |         ...state,
21 |         ...initialState,
22 |       };
23 |     default:
24 |       return state;
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/app/containers/App/Root.jsx:
--------------------------------------------------------------------------------
 1 | import React, { Component } from 'react';
 2 | import { Provider } from 'react-redux';
 3 | import { ConnectedRouter } from 'react-router-redux';
 4 | import '../../helpers/console';
 5 | 
 6 | import App from '.';
 7 | 
 8 | export default class Root extends Component {
 9 |   render() {
10 |     const { store, history } = this.props;
11 | 
12 |     return (
13 |       <Provider store={store}>
14 |         <ConnectedRouter history={history}>
15 |           <App />
16 |         </ConnectedRouter>
17 |       </Provider>
18 |     );
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/app/containers/App/actions.js:
--------------------------------------------------------------------------------
 1 | import prefixer from '../../helpers/reducerPrefixer';
 2 | 
 3 | const prefix = '@@App';
 4 | const actionTypesList = ['REQ_LOAD', 'RES_LOAD', 'FAIL_LOAD'];
 5 | 
 6 | export const actionTypes = prefixer(prefix, actionTypesList);
 7 | 
 8 | export function reqLoadApp() {
 9 |   return {
10 |     type: actionTypes.REQ_LOAD,
11 |   };
12 | }
13 | 
14 | export function resLoadApp() {
15 |   return {
16 |     type: actionTypes.RES_LOAD,
17 |   };
18 | }
19 | 
20 | export function failLoadApp(e) {
21 |   return {
22 |     type: actionTypes.FAIL_LOAD,
23 |     payload: {
24 |       error: e,
25 |     },
26 |   };
27 | }
28 | 


--------------------------------------------------------------------------------
/app/containers/App/components/Titlebar.jsx:
--------------------------------------------------------------------------------
 1 | import React, { PureComponent } from 'react';
 2 | import { withStyles } from '@material-ui/core/styles';
 3 | import { styles } from '../styles/Titlebar';
 4 | import { toggleWindowSizeOnDoubleClick } from '../../../helpers/titlebarDoubleClick';
 5 | import { APP_TITLEBAR_DOM_ID } from '../../../constants/dom';
 6 | import { capitalize, isEmpty, niceBytes } from '../../../utils/funcs';
 7 | import { getSelectedStorage } from '../../HomePage/actions';
 8 | import { getCurrentWindowHash } from '../../../helpers/windowHelper';
 9 | 
10 | class Titlebar extends PureComponent {
11 |   render() {
12 |     const { classes: styles, mtpDevice, mtpStoragesList, mtpMode } = this.props;
13 | 
14 |     const selectedStorage = getSelectedStorage(mtpStoragesList);
15 |     const windowHash = getCurrentWindowHash();
16 | 
17 |     return (
18 |       <div
19 |         onDoubleClick={() => {
20 |           toggleWindowSizeOnDoubleClick();
21 |         }}
22 |         className={styles.root}
23 |         id={APP_TITLEBAR_DOM_ID}
24 |       >
25 |         {/* Only show the device info. on the main window */}
26 |         {windowHash !== '/' ? null : mtpDevice?.isAvailable &&
27 |           mtpDevice?.info?.mtpDeviceInfo &&
28 |           !isEmpty(selectedStorage?.data?.info) ? (
29 |           <span className={styles.deviceInfo}>
30 |             <span className={styles.deviceModel}>
31 |               {`${mtpDevice?.info?.mtpDeviceInfo?.Model} (${selectedStorage?.data?.name}) - `}
32 |             </span>
33 |             {`${niceBytes(
34 |               parseInt(selectedStorage?.data.info?.FreeSpaceInBytes ?? 0, 10)
35 |             )} Free of ${niceBytes(
36 |               parseInt(selectedStorage?.data.info?.MaxCapability ?? 0, 10)
37 |             )}, ${capitalize(mtpMode)} Mode`}
38 |           </span>
39 |         ) : (
40 |           <span className={styles.deviceInfo}>
41 |             {`${capitalize(mtpMode)} Mode`}
42 |           </span>
43 |         )}
44 |       </div>
45 |     );
46 |   }
47 | }
48 | 
49 | export default withStyles(styles)(Titlebar);
50 | 


--------------------------------------------------------------------------------
/app/containers/App/reducers.js:
--------------------------------------------------------------------------------
 1 | export const initialState = {};
 2 | 
 3 | export default function App(state = initialState, action) {
 4 |   const { type } = action;
 5 | 
 6 |   switch (type) {
 7 |     default:
 8 |       return state;
 9 |   }
10 | }
11 | 


--------------------------------------------------------------------------------
/app/containers/App/selectors.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-unused-vars */
2 | 
3 | import { createSelector } from 'reselect';
4 | import { initialState } from './reducers';
5 | 
6 | const make = (state, props) => (state ? state.App : {});
7 | 
8 | /* eslint-enable no-unused-vars */
9 | 


--------------------------------------------------------------------------------
/app/containers/App/styles/Titlebar.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => {
 4 |   return {
 5 |     root: {
 6 |       width: `100%`,
 7 |       height: 14,
 8 |       textAlign: 'center',
 9 |       ...mixins({ theme }).appDragEnable,
10 |       ...mixins({ theme }).center,
11 |     },
12 |     deviceInfo: {
13 |       ...mixins({ theme }).center,
14 |       width: `100%`,
15 |       textAlign: 'center',
16 |       color: theme.palette.lightText1Color,
17 |       fontWeight: 'bold',
18 |       fontSize: '12px',
19 |     },
20 |     deviceModel: {
21 |       textTransform: 'capitalize',
22 |     },
23 |   };
24 | };
25 | 


--------------------------------------------------------------------------------
/app/containers/AppFeaturesPage/Loadable.js:
--------------------------------------------------------------------------------
 1 | import React, { lazy, Suspense } from 'react';
 2 | import LoadingIndicator from '../../components/LoadingIndicator';
 3 | 
 4 | const Component = lazy(() => import('.'));
 5 | 
 6 | export default function loadable() {
 7 |   return (
 8 |     <Suspense fallback={<LoadingIndicator />}>
 9 |       <Component />
10 |     </Suspense>
11 |   );
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/AppFeaturesPage/index.jsx:
--------------------------------------------------------------------------------
 1 | import React, { Component } from 'react';
 2 | import { withStyles } from '@material-ui/core/styles';
 3 | import { Helmet } from 'react-helmet';
 4 | import { APP_TITLE } from '../../constants/meta';
 5 | import { resetOverFlowY } from '../../utils/styleResets';
 6 | import { styles } from './styles';
 7 | import Features from '../Onboarding/components/Features';
 8 | import WhatsNew from '../Onboarding/components/WhatsNew';
 9 | import { APP_FEATURES_PAGE_TITLE } from '../../templates/appFeaturesPage';
10 | 
11 | class AppFeaturesPage extends Component {
12 |   componentWillMount() {
13 |     resetOverFlowY();
14 |   }
15 | 
16 |   render() {
17 |     const { classes: styles } = this.props;
18 | 
19 |     return (
20 |       <div className={styles.root}>
21 |         <Helmet titleTemplate={`%s - ${APP_TITLE}`}>
22 |           <title>{APP_FEATURES_PAGE_TITLE}</title>
23 |         </Helmet>
24 |         <div className={styles.body}>
25 |           <Features hideTitle={false} />
26 |           <div className={styles.marginDivider} />
27 |           <WhatsNew hideTitle={false} />
28 |         </div>
29 |       </div>
30 |     );
31 |   }
32 | }
33 | 
34 | export default withStyles(styles)(AppFeaturesPage);
35 | 


--------------------------------------------------------------------------------
/app/containers/AppFeaturesPage/styles/index.js:
--------------------------------------------------------------------------------
 1 | export const styles = (_) => ({
 2 |   root: {
 3 |     textAlign: `left`,
 4 |     padding: '10px 30px 30px 30px',
 5 |     maxWidth: '800px',
 6 |     marginRight: 'auto',
 7 |     marginLeft: 'auto',
 8 |     overflow: 'auto',
 9 |   },
10 |   heading: {},
11 |   body: {},
12 |   marginDivider: {
13 |     height: 15,
14 |   },
15 | });
16 | 


--------------------------------------------------------------------------------
/app/containers/AppUpdatePage/UpdateAvailable/Loadable.js:
--------------------------------------------------------------------------------
 1 | import React, { lazy, Suspense } from 'react';
 2 | import LoadingIndicator from '../../../components/LoadingIndicator';
 3 | 
 4 | const Component = lazy(() => import('.'));
 5 | 
 6 | export default function loadable() {
 7 |   return (
 8 |     <Suspense fallback={<LoadingIndicator />}>
 9 |       <Component />
10 |     </Suspense>
11 |   );
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/AppUpdatePage/UpdateAvailable/styles/index.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   root: {
 5 |     padding: `0 25px 10px 25px`,
 6 |   },
 7 | 
 8 |   loadingText: { padding: 15 },
 9 | 
10 |   title: {
11 |     fontWeight: `bold`,
12 |   },
13 | 
14 |   releaseNotes: {
15 |     fontWeight: `bold`,
16 |     marginTop: 10,
17 |   },
18 | 
19 |   scrollContainer: {
20 |     ...mixins({ theme }).center,
21 |     marginTop: 5,
22 |     border: `1px solid #000`,
23 |     background: theme.palette.background.paper,
24 |     height: 350,
25 |     width: '100%',
26 |     padding: 15,
27 |     overflowX: 'auto',
28 |     overflowY: 'auto',
29 |   },
30 | 
31 |   btnWrapper: {
32 |     position: `absolute`,
33 |     bottom: 15,
34 |     right: 24,
35 |   },
36 | 
37 |   btnPositive: {
38 |     ...mixins({ theme }).btnPositive,
39 |     margin: `0 0 0 10px`,
40 |   },
41 | 
42 |   btnNegative: {
43 |     ...mixins({ theme }).btnNegativeWhite,
44 |   },
45 | });
46 | 


--------------------------------------------------------------------------------
/app/containers/AppUpdatePage/UpdateAvailable/styles/release-notes.scss:
--------------------------------------------------------------------------------
 1 | .releaseNotes {
 2 |   h1,
 3 |   h2,
 4 |   h3,
 5 |   h4,
 6 |   h5,
 7 |   h6,
 8 |   p,
 9 |   ul {
10 |     margin-top: 0;
11 |     margin-bottom: 10px;
12 |     line-height: 22px;
13 |   }
14 |   li {
15 |     line-height: 22px;
16 |   }
17 | }
18 | 


--------------------------------------------------------------------------------
/app/containers/AppUpdatePage/UpdateProgress/Loadable.js:
--------------------------------------------------------------------------------
 1 | import React, { lazy, Suspense } from 'react';
 2 | import LoadingIndicator from '../../../components/LoadingIndicator';
 3 | 
 4 | const Component = lazy(() => import('.'));
 5 | 
 6 | export default function loadable() {
 7 |   return (
 8 |     <Suspense fallback={<LoadingIndicator />}>
 9 |       <Component />
10 |     </Suspense>
11 |   );
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/AppUpdatePage/UpdateProgress/index.jsx:
--------------------------------------------------------------------------------
 1 | import { ipcRenderer } from 'electron';
 2 | import React, { Component } from 'react';
 3 | import { withStyles } from '@material-ui/core/styles';
 4 | import LinearProgress from '@material-ui/core/LinearProgress';
 5 | import Typography from '@material-ui/core/Typography';
 6 | import { styles } from './styles';
 7 | 
 8 | class ProgressbarPage extends Component {
 9 |   constructor(props) {
10 |     super(props);
11 | 
12 |     this.initialState = {
13 |       progressTitle: `Progress...`,
14 |       progressBodyText: `Progress...`,
15 |       value: 0,
16 |       variant: `indeterminate`,
17 |     };
18 | 
19 |     this.state = {
20 |       ...this.initialState,
21 |     };
22 |   }
23 | 
24 |   componentWillMount() {
25 |     ipcRenderer.on(
26 |       'appUpdatesProgressBarCommunication',
27 |       (event, { ...args }) => {
28 |         this.setState({ ...args });
29 |       }
30 |     );
31 |   }
32 | 
33 |   componentWillUnmount() {
34 |     ipcRenderer.removeListener('appUpdatesProgressBarCommunication', () => {});
35 |   }
36 | 
37 |   render() {
38 |     const { classes: styles } = this.props;
39 |     const { progressTitle, progressBodyText, value, variant } = this.state;
40 | 
41 |     return (
42 |       <div className={styles.root}>
43 |         <Typography variant="body1" className={styles.progressTitle}>
44 |           {progressTitle}
45 |         </Typography>
46 |         <Typography variant="body1" className={styles.progressBodyText}>
47 |           {progressBodyText}
48 |         </Typography>
49 |         <LinearProgress color="secondary" variant={variant} value={value} />
50 |       </div>
51 |     );
52 |   }
53 | }
54 | 
55 | export default withStyles(styles)(ProgressbarPage);
56 | 


--------------------------------------------------------------------------------
/app/containers/AppUpdatePage/UpdateProgress/styles/index.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   root: {
 5 |     textAlign: `left`,
 6 |     ...mixins({ theme }).center,
 7 |     width: 500,
 8 |     marginTop: 10,
 9 |   },
10 |   progressBodyText: {
11 |     marginBottom: 10,
12 |   },
13 |   progressTitle: {
14 |     fontWeight: 'bold',
15 |     marginBottom: 10,
16 |   },
17 | });
18 | 


--------------------------------------------------------------------------------
/app/containers/ErrorBoundary/styles/GenerateErrorReport.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   subHeading: {
 5 |     ...mixins({ theme }).noDrag,
 6 |     ...mixins({ theme }).noselect,
 7 |     marginTop: 15,
 8 |   },
 9 |   instructions: {
10 |     listStyle: `none`,
11 |     color: theme.palette.lightText1Color,
12 |     lineHeight: '24px',
13 |     marginTop: 15,
14 |     paddingLeft: 0,
15 |     marginBottom: 15,
16 |   },
17 |   generateLogsBtnWrapper: {},
18 |   generateLogsBtn: {
19 |     marginTop: 0,
20 |     ...mixins({ theme }).btnPositive,
21 |   },
22 |   emailIdWrapper: {
23 |     color: theme.palette.lightText1Color,
24 |     marginTop: 15,
25 |   },
26 |   emailId: {
27 |     marginLeft: 16,
28 |     fontWeight: `bold`,
29 |   },
30 | });
31 | 


--------------------------------------------------------------------------------
/app/containers/ErrorBoundary/styles/index.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   root: {
 5 |     textAlign: `center`,
 6 |     ...mixins({ theme }).center,
 7 |     ...mixins({ theme }).absoluteCenter,
 8 |   },
 9 |   bugImg: {
10 |     ...mixins({ theme }).noDrag,
11 |     height: `auto`,
12 |     width: 150,
13 |   },
14 |   headings: {
15 |     ...mixins({ theme }).noDrag,
16 |     ...mixins({ theme }).noselect,
17 |     marginTop: 15,
18 |   },
19 |   subHeading: {
20 |     ...mixins({ theme }).noDrag,
21 |     ...mixins({ theme }).noselect,
22 |     marginTop: 15,
23 |   },
24 |   goBackBtn: {
25 |     marginTop: 5,
26 |   },
27 | });
28 | 


--------------------------------------------------------------------------------
/app/containers/HelpFaqsPage/Loadable.js:
--------------------------------------------------------------------------------
 1 | import React, { lazy, Suspense } from 'react';
 2 | import LoadingIndicator from '../../components/LoadingIndicator';
 3 | 
 4 | const Component = lazy(() => import('.'));
 5 | 
 6 | export default function loadable({ ...props }) {
 7 |   return (
 8 |     <Suspense fallback={<LoadingIndicator />}>
 9 |       <Component {...props} />
10 |     </Suspense>
11 |   );
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/HelpFaqsPage/index.jsx:
--------------------------------------------------------------------------------
 1 | import React, { Component } from 'react';
 2 | import { withStyles } from '@material-ui/core/styles';
 3 | import Typography from '@material-ui/core/Typography';
 4 | import { connect } from 'react-redux';
 5 | import { bindActionCreators } from 'redux';
 6 | import { Helmet } from 'react-helmet';
 7 | import { APP_TITLE } from '../../constants/meta';
 8 | import { resetOverFlowY } from '../../utils/styleResets';
 9 | import { styles } from './styles';
10 | import {
11 |   FAQS_PAGE_TITLE,
12 |   HELP_PHONE_IS_NOT_CONNECTING,
13 | } from '../../templates/helpFaqsPage';
14 | import HelpPhoneNotRecognized from './components/HelpPhoneNotRecognized';
15 | 
16 | class FaqsPage extends Component {
17 |   componentWillMount() {
18 |     resetOverFlowY();
19 |   }
20 | 
21 |   render() {
22 |     const { classes: styles, showPhoneNotRecognizedNote } = this.props;
23 | 
24 |     const title = showPhoneNotRecognizedNote
25 |       ? HELP_PHONE_IS_NOT_CONNECTING
26 |       : FAQS_PAGE_TITLE;
27 | 
28 |     return (
29 |       <div className={styles.root}>
30 |         <Helmet titleTemplate={`%s - ${APP_TITLE}`}>
31 |           <title>{title}</title>
32 |         </Helmet>
33 |         <Typography variant="h5" className={styles.heading}>
34 |           {title}
35 |         </Typography>
36 |         <div className={styles.body}>
37 |           <HelpPhoneNotRecognized
38 |             showPhoneNotRecognizedNote={showPhoneNotRecognizedNote}
39 |           />
40 |         </div>
41 |       </div>
42 |     );
43 |   }
44 | }
45 | 
46 | const mapDispatchToProps = (dispatch, __) => bindActionCreators({}, dispatch);
47 | 
48 | const mapStateToProps = (_, __) => {
49 |   return {};
50 | };
51 | 
52 | export default connect(
53 |   mapStateToProps,
54 |   mapDispatchToProps
55 | )(withStyles(styles)(FaqsPage));
56 | 


--------------------------------------------------------------------------------
/app/containers/HelpFaqsPage/styles/HelpPhoneNotRecognized.js:
--------------------------------------------------------------------------------
 1 | import mixins from '../../../styles/js/mixins';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   root: {},
 5 |   expansionRoot: {
 6 |     background: theme.palette.tableHeaderFooterBgColor,
 7 |   },
 8 |   heading: {
 9 |     fontWeight: 600,
10 |   },
11 |   imagePlaceholder: {
12 |     width: 200,
13 |     height: 'auto',
14 |   },
15 |   imgWrapper: {
16 |     ...mixins({ theme }).center,
17 |     textAlign: 'center',
18 |   },
19 | });
20 | 


--------------------------------------------------------------------------------
/app/containers/HelpFaqsPage/styles/index.js:
--------------------------------------------------------------------------------
 1 | export const styles = (_) => ({
 2 |   root: {
 3 |     textAlign: `left`,
 4 |     padding: '30px 30px 30px 30px',
 5 |     maxWidth: 950,
 6 |     marginRight: 'auto',
 7 |     marginLeft: 'auto',
 8 |     overflow: 'auto',
 9 |   },
10 |   a: {
11 |     fontWeight: `bold`,
12 |   },
13 |   heading: {},
14 |   body: {
15 |     paddingTop: 25,
16 |   },
17 | });
18 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/Loadable.js:
--------------------------------------------------------------------------------
 1 | import React, { lazy, Suspense } from 'react';
 2 | import LoadingIndicator from '../../components/LoadingIndicator';
 3 | 
 4 | const Component = lazy(() => import('.'));
 5 | 
 6 | export default function loadable() {
 7 |   return (
 8 |     <Suspense fallback={<LoadingIndicator />}>
 9 |       <Component />
10 |     </Suspense>
11 |   );
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/components/FileExplorerTableFooterRender.jsx:
--------------------------------------------------------------------------------
 1 | import React, { PureComponent } from 'react';
 2 | import { withStyles } from '@material-ui/core/styles';
 3 | import TableFooter from '@material-ui/core/TableFooter';
 4 | import { styles } from '../styles/FileExplorerTableFooterRender';
 5 | import Breadcrumb from '../../../components/Breadcrumb';
 6 | import FileExplorerTableFooterStatusBarRender from './FileExplorerTableFooterStatusBarRender';
 7 | 
 8 | class FileExplorerTableFooterRender extends PureComponent {
 9 |   render() {
10 |     const {
11 |       classes: styles,
12 |       currentBrowsePath,
13 |       deviceType,
14 |       onBreadcrumbPathClick,
15 |       isStatusBarEnabled,
16 |       directoryLists,
17 |       fileTransferClipboard,
18 |       mtpDevice,
19 |     } = this.props;
20 | 
21 |     return (
22 |       <TableFooter component="div" className={styles.tableFooter}>
23 |         {isStatusBarEnabled && (
24 |           <FileExplorerTableFooterStatusBarRender
25 |             directoryLists={directoryLists}
26 |             fileTransferClipboard={fileTransferClipboard}
27 |             deviceType={deviceType}
28 |             mtpDevice={mtpDevice}
29 |           />
30 |         )}
31 |         <Breadcrumb
32 |           onBreadcrumbPathClick={onBreadcrumbPathClick}
33 |           currentBrowsePath={currentBrowsePath[deviceType]}
34 |           deviceType={deviceType}
35 |         />
36 |       </TableFooter>
37 |     );
38 |   }
39 | }
40 | 
41 | export default withStyles(styles)(FileExplorerTableFooterRender);
42 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorer.js:
--------------------------------------------------------------------------------
 1 | export const styles = (theme) => ({
 2 |   socialMediaShareContainer: {
 3 |     paddingTop: 5,
 4 |   },
 5 |   supportBtnsTitle: {
 6 |     marginBottom: 10,
 7 |     fontSize: 12,
 8 |     fontWeight: 500,
 9 |   },
10 |   supportBtnsTitleNewLine: {
11 |     display: 'block',
12 |   },
13 |   supportBtnsBoldText: {
14 |     fontWeight: 'bold',
15 |   },
16 |   socialMediaShareTitle: {
17 |     marginTop: 10,
18 |     fontSize: 11,
19 |     fontWeight: 500,
20 |   },
21 |   socialMediaShareBtnsContainer: {
22 |     width: '100%',
23 |     display: 'flex',
24 |     alignItems: 'center',
25 |   },
26 |   socialMediaBtnWrapper: {
27 |     width: 50,
28 |     height: 50,
29 |   },
30 |   socialMediaBtnWrapperForImage: {
31 |     padding: `7px !important`,
32 |     background: '#fff',
33 |     [`&:hover`]: {
34 |       background: `rgba(255, 255, 255, 0.85) !important`,
35 |     },
36 |   },
37 |   socialMediaShareBtn: {
38 |     height: 22,
39 |     width: `22px`,
40 |     color: theme.palette.contrastPrimaryMainColor,
41 |   },
42 |   socialMediaShareBtnImages: {
43 |     height: 23,
44 |     width: 23,
45 |   },
46 |   imageBtn: {
47 |     padding: `7px !important`,
48 |     background: '#fff',
49 |     [`&:hover`]: {
50 |       background: `rgba(255, 255, 255, 0.85) !important`,
51 |     },
52 |   },
53 | 
54 |   supportBtnsContainer: {
55 |     width: `100%`,
56 |     display: `flex`,
57 |   },
58 |   supportBtnWrapper: {
59 |     width: 'auto',
60 |   },
61 |   supportBtnWrapperForImage: {
62 |     padding: `0px 10px 5px 0 !important`,
63 |   },
64 |   supportBtnImages: {
65 |     width: `100%`,
66 |     height: 40,
67 |     cursor: 'pointer',
68 | 
69 |     [`&:hover`]: {
70 |       filter: `brightness(0.85)`,
71 |     },
72 | 
73 |     [`&.paypal`]: {
74 |       background: `#fff`,
75 |       borderRadius: 7,
76 |       padding: 7,
77 |     },
78 |   },
79 | });
80 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorerBodyRender.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   root: {
 5 |     width: '100%',
 6 |     ...mixins({ theme }).noselect,
 7 |   },
 8 |   tableWrapper: {
 9 |     ...mixins({ theme }).noOutline,
10 |     height: `calc(100vh - 120px)`,
11 |     overflowY: 'auto',
12 |     overflowX: 'auto',
13 |     borderBottom: `solid 1px ${theme.palette.fileExplorerThinLineDividerColor}`,
14 |     borderLeft: `solid 1px ${theme.palette.fileExplorerThinLineDividerColor}`,
15 |     [`&.onHoverDropZone`]: {
16 |       backgroundColor: theme.palette.fileDrop,
17 |     },
18 |     [`&.statusBarActive`]: {
19 |       height: `calc(100vh - 150px) !important`,
20 |     },
21 |   },
22 | });
23 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorerTableBodyEmptyRender.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | import { tableCellFileExplorerTableRowsRender } from './FileExplorerTableBodyListRender';
 3 | 
 4 | export const styles = (theme) => ({
 5 |   emptyTableRowWrapper: {},
 6 |   tableCell: tableCellFileExplorerTableRowsRender,
 7 |   helpPhoneNotRecognized: {
 8 |     width: '100%',
 9 |     ...mixins({ theme }).center,
10 |     color: theme.palette.snackbar.error,
11 |     fontWeight: 600,
12 |   },
13 |   noMtp: {
14 |     marginTop: 10,
15 |   },
16 |   instructions: {
17 |     marginTop: 5,
18 |     lineHeight: `18px`,
19 |     paddingLeft: 30,
20 |     color: `rgba(0, 0, 0, 0.8)`,
21 |   },
22 |   nestedPanel: {
23 |     paddingLeft: 16,
24 |     paddingRight: 16,
25 |   },
26 |   divider: {
27 |     marginTop: 10,
28 |     marginBottom: 10,
29 |   },
30 | });
31 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorerTableBodyGridRender.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   wrapper: {},
 5 |   itemWrapper: {
 6 |     float: `left`,
 7 |     width: 100,
 8 |     height: 137,
 9 |   },
10 |   itemCheckBox: {
11 |     display: `none`,
12 |   },
13 |   fileTypeIcon: {
14 |     width: 'auto',
15 |     height: 80,
16 |   },
17 |   fileTypeIconWrapper: {
18 |     ...mixins({ theme }).center,
19 |     paddingTop: 10,
20 |     paddingBottom: 10,
21 |     textAlign: 'center',
22 |   },
23 |   itemSelected: {
24 |     backgroundColor: 'rgba(41, 121, 255, 0.15) !important',
25 |   },
26 |   itemFileName: {
27 |     wordBreak: `break-all`,
28 |     textAlign: `center`,
29 |   },
30 |   itemFileNameWrapper: {
31 |     marginLeft: 12,
32 |     marginRight: 12,
33 |     marginTop: -8,
34 |     textAlign: `center`,
35 |   },
36 | });
37 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorerTableBodyGridWrapperRender.js:
--------------------------------------------------------------------------------
1 | export const styles = (_) => ({
2 |   wrapper: {},
3 |   gridTableCell: {
4 |     paddingLeft: `5px !important`,
5 |     paddingRight: `5px !important`,
6 |     border: 0,
7 |   },
8 | });
9 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorerTableBodyListRender.js:
--------------------------------------------------------------------------------
 1 | export const tableCellFileExplorerTableRowsRender = {
 2 |   borderBottom: `unset`,
 3 |   [`&.checkboxCell`]: {
 4 |     width: 50,
 5 |   },
 6 |   [`&.nameCell`]: {
 7 |     display: 'flex',
 8 |     alignItems: 'center',
 9 |     whiteSpace: `nowrap`,
10 |     overflow: `hidden`,
11 |     textOverflow: `ellipsis`,
12 |   },
13 |   [`&.sizeCell`]: {
14 |     whiteSpace: `nowrap`,
15 |     overflow: `hidden`,
16 |     textOverflow: `ellipsis`,
17 |     width: `auto`,
18 |     minWidth: 100,
19 |   },
20 |   [`&.dateAddedCell`]: {
21 |     whiteSpace: `nowrap`,
22 |     overflow: `hidden`,
23 |     textOverflow: `ellipsis`,
24 |     width: `auto`,
25 |     minWidth: 100,
26 |     paddingRight: 10,
27 |   },
28 | };
29 | 
30 | export const styles = (_) => {
31 |   return {
32 |     tableRowSelected: {
33 |       backgroundColor: 'rgba(41, 121, 255, 0.15) !important',
34 |     },
35 |     tableCell: tableCellFileExplorerTableRowsRender,
36 |     fileTypeIconWrapper: {
37 |       paddingTop: 5,
38 |       paddingBottom: 5,
39 |       paddingLeft: 2,
40 |       textAlign: 'center',
41 |     },
42 |     fileTypeIcon: {
43 |       verticalAlign: `middle`,
44 |       height: 20,
45 |       width: 'auto',
46 |     },
47 |     truncate: {
48 |       textOverflow: 'ellipsis',
49 |       overflow: 'hidden',
50 |       maxWidth: 310,
51 |       whiteSpace: 'nowrap',
52 |     },
53 |   };
54 | };
55 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorerTableBodyRender.js:
--------------------------------------------------------------------------------
1 | export const styles = (_) => ({
2 |   table: {},
3 | });
4 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorerTableFooterRender.js:
--------------------------------------------------------------------------------
1 | export const styles = (_) => ({
2 |   tableFooter: {
3 |     display: 'unset !important',
4 |   },
5 | });
6 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorerTableFooterStatusBarRender.js:
--------------------------------------------------------------------------------
 1 | export const styles = (theme) => ({
 2 |   root: {
 3 |     padding: '5px 15px 0 15px',
 4 |     width: '100%',
 5 |     background: theme.palette.tableHeaderFooterBgColor,
 6 |     height: 30,
 7 |     textAlign: 'center',
 8 |   },
 9 | 
10 |   deviceTypeWrapper: {
11 |     fontWeight: '500',
12 |     color: theme.palette.secondary.main,
13 |     marginLeft: 5,
14 |     fontSize: 12,
15 |     textTransform: 'capitalize',
16 | 
17 |     [`& span`]: {
18 |       color: theme.palette.contrastPrimaryMainColor,
19 |       fontWeight: '600',
20 |       fontSize: 13,
21 |     },
22 |   },
23 | 
24 |   bodyWrapper: {
25 |     fontWeight: '500',
26 |     color: theme.palette.lightText1Color,
27 |   },
28 | });
29 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/FileExplorerTableHeadRender.js:
--------------------------------------------------------------------------------
 1 | export const styles = (theme) => ({
 2 |   tableHeadCell: {
 3 |     border: `unset`,
 4 |     backgroundColor: theme.palette.tableHeaderFooterBgColor,
 5 |     position: 'sticky',
 6 |     top: 0,
 7 |     zIndex: 10,
 8 |   },
 9 | });
10 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/SidebarAreaPaneLists.js:
--------------------------------------------------------------------------------
 1 | import { variables } from '../../../styles/js';
 2 | 
 3 | export const styles = (_) => {
 4 |   return {
 5 |     listsWrapper: {
 6 |       paddingTop: variables().sizes.sidebarAreaPaddingTop,
 7 |       width: variables().sizes.sidebarAreaPaneWidth,
 8 |     },
 9 |     listsBottom: {
10 |       paddingTop: 5,
11 |     },
12 |     listIcon: {
13 |       minWidth: 35,
14 |     },
15 |     listsCaption: {
16 |       padding: `14px 0 0px 20px`,
17 |     },
18 |     primary: {},
19 |     icon: {},
20 |   };
21 | };
22 | 


--------------------------------------------------------------------------------
/app/containers/HomePage/styles/index.js:
--------------------------------------------------------------------------------
 1 | export const styles = (_) => {
 2 |   return {
 3 |     root: {},
 4 |     grid: {
 5 |       width: `100%`,
 6 |     },
 7 |     splitPane: {
 8 |       width: `50%`,
 9 |       float: `left`,
10 |       [`&:after`]: {
11 |         content: '""',
12 |         display: `table`,
13 |         clear: `both`,
14 |       },
15 |     },
16 |     singlePane: {
17 |       width: `100% !important`,
18 |     },
19 |   };
20 | };
21 | 


--------------------------------------------------------------------------------
/app/containers/KeyboardShortcutsPage/Loadable.js:
--------------------------------------------------------------------------------
 1 | import React, { lazy, Suspense } from 'react';
 2 | import LoadingIndicator from '../../components/LoadingIndicator';
 3 | 
 4 | const Component = lazy(() => import('.'));
 5 | 
 6 | export default function loadable() {
 7 |   return (
 8 |     <Suspense fallback={<LoadingIndicator />}>
 9 |       <Component />
10 |     </Suspense>
11 |   );
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/KeyboardShortcutsPage/components/KbdRender.jsx:
--------------------------------------------------------------------------------
 1 | import React, { PureComponent } from 'react';
 2 | import { quickHash } from '../../../utils/funcs';
 3 | import { fileExplorerKeymaps } from '../../../constants/keymaps';
 4 | 
 5 | export default class KbdRender extends PureComponent {
 6 |   render() {
 7 |     const { styles } = this.props;
 8 | 
 9 |     return Object.keys(fileExplorerKeymaps).map((a) => {
10 |       const item = fileExplorerKeymaps[a];
11 | 
12 |       return (
13 |         <div key={a}>
14 |           <div className={styles.kbdWrapper}>
15 |             <span className={styles.kbdTitle}>{item.label}</span>
16 |             <div className={styles.kbdInnerWrapper}>
17 |               {item.keys.map((key, keyIndex) => {
18 |                 const keySplit = key.split('+');
19 | 
20 |                 return (
21 |                   <span key={quickHash(key)}>
22 |                     {keySplit.map((f, fIndex) => {
23 |                       return (
24 |                         <span key={quickHash(f)}>
25 |                           <kbd>{f}</kbd>
26 |                           {fIndex === keySplit.length - 1 ? null : `+`}
27 |                         </span>
28 |                       );
29 |                     })}
30 |                     {keyIndex === item.keys.length - 1 ? null : ` or `}
31 |                   </span>
32 |                 );
33 |               })}
34 |             </div>
35 |           </div>
36 |         </div>
37 |       );
38 |     });
39 |   }
40 | }
41 | 


--------------------------------------------------------------------------------
/app/containers/KeyboardShortcutsPage/components/KeyboadShortcuts.jsx:
--------------------------------------------------------------------------------
 1 | import React, { PureComponent } from 'react';
 2 | import { withStyles } from '@material-ui/core/styles';
 3 | import { styles } from '../styles/KeyboadShortcuts';
 4 | import KbdRender from './KbdRender';
 5 | 
 6 | class KeyboadShortcuts extends PureComponent {
 7 |   render() {
 8 |     const { classes: styles } = this.props;
 9 | 
10 |     return (
11 |       <div className={styles.root}>
12 |         <KbdRender styles={styles} />
13 |       </div>
14 |     );
15 |   }
16 | }
17 | 
18 | export default withStyles(styles)(KeyboadShortcuts);
19 | 


--------------------------------------------------------------------------------
/app/containers/KeyboardShortcutsPage/index.jsx:
--------------------------------------------------------------------------------
 1 | import React, { Component } from 'react';
 2 | import { withStyles } from '@material-ui/core/styles';
 3 | import Typography from '@material-ui/core/Typography';
 4 | import { Helmet } from 'react-helmet';
 5 | import { APP_TITLE } from '../../constants/meta';
 6 | import { resetOverFlowY } from '../../utils/styleResets';
 7 | import { styles } from './styles';
 8 | import KeyboadShortcuts from './components/KeyboadShortcuts';
 9 | import { KEYBOARD_SHORTCUTS_PAGE_TITLE } from '../../templates/keyboardShortcutsPage';
10 | 
11 | class KeyboardShortcutsPage extends Component {
12 |   componentWillMount() {
13 |     resetOverFlowY();
14 |   }
15 | 
16 |   render() {
17 |     const { classes: styles } = this.props;
18 | 
19 |     return (
20 |       <div className={styles.root}>
21 |         <Helmet titleTemplate={`%s - ${APP_TITLE}`}>
22 |           <title>{KEYBOARD_SHORTCUTS_PAGE_TITLE}</title>
23 |         </Helmet>
24 |         <Typography variant="h6" color="secondary">
25 |           Keyboard Shortcuts
26 |         </Typography>
27 |         <div className={styles.body}>
28 |           <KeyboadShortcuts />
29 |         </div>
30 |       </div>
31 |     );
32 |   }
33 | }
34 | 
35 | export default withStyles(styles)(KeyboardShortcutsPage);
36 | 


--------------------------------------------------------------------------------
/app/containers/KeyboardShortcutsPage/styles/KeyboadShortcuts.js:
--------------------------------------------------------------------------------
 1 | export const styles = (theme) => ({
 2 |   root: {},
 3 |   title: {
 4 |     fontWeight: `bold`,
 5 |   },
 6 |   kbdWrapper: {
 7 |     paddingBottom: 14,
 8 |   },
 9 |   kbdInnerWrapper: {
10 |     display: `inline-block`,
11 |   },
12 |   kbdTitle: {
13 |     display: 'block',
14 |     color: theme.palette.lightText1Color,
15 |     padding: '1px 0 6px 0',
16 |     fontSize: 14,
17 |   },
18 | });
19 | 


--------------------------------------------------------------------------------
/app/containers/KeyboardShortcutsPage/styles/index.js:
--------------------------------------------------------------------------------
 1 | export const styles = (_) => ({
 2 |   root: {
 3 |     textAlign: `left`,
 4 |     padding: '0 30px 30px 30px',
 5 |     maxWidth: '800px',
 6 |     marginRight: 'auto',
 7 |     marginLeft: 'auto',
 8 |     overflow: 'auto',
 9 |   },
10 |   heading: {
11 |     fontWeight: 'bold',
12 |   },
13 |   body: {
14 |     marginTop: 10,
15 |   },
16 | });
17 | 


--------------------------------------------------------------------------------
/app/containers/NotFoundPage/Loadable.js:
--------------------------------------------------------------------------------
 1 | import React, { lazy, Suspense } from 'react';
 2 | import LoadingIndicator from '../../components/LoadingIndicator';
 3 | 
 4 | const Component = lazy(() => import('.'));
 5 | 
 6 | export default function loadable() {
 7 |   return (
 8 |     <Suspense fallback={<LoadingIndicator />}>
 9 |       <Component />
10 |     </Suspense>
11 |   );
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/NotFoundPage/index.jsx:
--------------------------------------------------------------------------------
 1 | import React, { Component, Fragment } from 'react';
 2 | import { Link } from 'react-router-dom';
 3 | import { Helmet } from 'react-helmet';
 4 | import { routes } from '../../routing';
 5 | import styles from './styles/index.scss';
 6 | import { APP_TITLE } from '../../constants/meta';
 7 | 
 8 | export default class NotFound extends Component {
 9 |   render() {
10 |     return (
11 |       <Fragment>
12 |         <Helmet titleTemplate={`%s - ${APP_TITLE}`}>
13 |           <title>Resource not found!</title>
14 |         </Helmet>
15 |         <div className={styles.container}>
16 |           <h1>Resource not found!</h1>
17 |           <Link to={routes.Home.path}>Go back</Link>
18 |         </div>
19 |       </Fragment>
20 |     );
21 |   }
22 | }
23 | 


--------------------------------------------------------------------------------
/app/containers/NotFoundPage/styles/index.scss:
--------------------------------------------------------------------------------
 1 | .container {
 2 |   width: 500px;
 3 |   margin-left: auto;
 4 |   margin-right: auto;
 5 |   text-align: center;
 6 |   h2 {
 7 |     font-size: 2rem;
 8 |   }
 9 |   a {
10 |     font-size: 1.4rem;
11 |   }
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/Onboarding/styles/Features.js:
--------------------------------------------------------------------------------
1 | export const styles = (_) => ({
2 |   root: {},
3 |   title: {
4 |     fontWeight: `bold`,
5 |   },
6 | });
7 | 


--------------------------------------------------------------------------------
/app/containers/Onboarding/styles/WhatsNew.js:
--------------------------------------------------------------------------------
 1 | export const styles = (_) => ({
 2 |   root: {},
 3 |   title: {
 4 |     fontWeight: `bold`,
 5 |   },
 6 |   nestedPanel: {
 7 |     paddingLeft: 16,
 8 |     paddingRight: 16,
 9 |   },
10 | });
11 | 


--------------------------------------------------------------------------------
/app/containers/Onboarding/styles/index.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   root: {},
 5 |   btnPositive: {
 6 |     ...mixins({ theme }).btnPositive,
 7 |   },
 8 |   divider: {
 9 |     marginBottom: 20,
10 |   },
11 |   contentBox: {
12 |     padding: 25,
13 |     background: 'rgba(224, 224, 224, 0.12)',
14 |   },
15 | });
16 | 


--------------------------------------------------------------------------------
/app/containers/PrivacyPolicyPage/Loadable.js:
--------------------------------------------------------------------------------
 1 | import React, { lazy, Suspense } from 'react';
 2 | import LoadingIndicator from '../../components/LoadingIndicator';
 3 | 
 4 | const Component = lazy(() => import('.'));
 5 | 
 6 | export default function loadable() {
 7 |   return (
 8 |     <Suspense fallback={<LoadingIndicator />}>
 9 |       <Component />
10 |     </Suspense>
11 |   );
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/PrivacyPolicyPage/styles/index.js:
--------------------------------------------------------------------------------
 1 | export const styles = (_) => ({
 2 |   root: {
 3 |     textAlign: `left`,
 4 |     padding: '30px 30px 30px 30px',
 5 |     maxWidth: '800px',
 6 |     marginRight: 'auto',
 7 |     marginLeft: 'auto',
 8 |     overflow: 'auto',
 9 |   },
10 |   a: {
11 |     fontWeight: `bold`,
12 |   },
13 |   heading: {},
14 |   body: {
15 |     lineHeight: `22px`,
16 |   },
17 | });
18 | 


--------------------------------------------------------------------------------
/app/containers/ReportBugsPage/Loadable.js:
--------------------------------------------------------------------------------
 1 | import React, { lazy, Suspense } from 'react';
 2 | import LoadingIndicator from '../../components/LoadingIndicator';
 3 | 
 4 | const Component = lazy(() => import('.'));
 5 | 
 6 | export default function loadable() {
 7 |   return (
 8 |     <Suspense fallback={<LoadingIndicator />}>
 9 |       <Component />
10 |     </Suspense>
11 |   );
12 | }
13 | 


--------------------------------------------------------------------------------
/app/containers/ReportBugsPage/index.jsx:
--------------------------------------------------------------------------------
 1 | import React, { Component } from 'react';
 2 | import { withStyles } from '@material-ui/core/styles';
 3 | import { Helmet } from 'react-helmet';
 4 | import { connect } from 'react-redux';
 5 | import { bindActionCreators } from 'redux';
 6 | import GenerateErrorReport from '../ErrorBoundary/components/GenerateErrorReport';
 7 | import { APP_TITLE } from '../../constants/meta';
 8 | import { styles } from './styles';
 9 | import { REPORT_BUGS_PAGE_TITLE } from '../../templates/generateErrorReport';
10 | 
11 | class ReportBugsPage extends Component {
12 |   render() {
13 |     const { classes: styles } = this.props;
14 | 
15 |     return (
16 |       <div className={styles.root}>
17 |         <Helmet titleTemplate={`%s - ${APP_TITLE}`}>
18 |           <title>{REPORT_BUGS_PAGE_TITLE}</title>
19 |         </Helmet>
20 |         <GenerateErrorReport isReportBugsPage />
21 |       </div>
22 |     );
23 |   }
24 | }
25 | 
26 | const mapDispatchToProps = (dispatch, __) => bindActionCreators({}, dispatch);
27 | 
28 | const mapStateToProps = (_, __) => {
29 |   return {};
30 | };
31 | 
32 | export default connect(
33 |   mapStateToProps,
34 |   mapDispatchToProps
35 | )(withStyles(styles)(ReportBugsPage));
36 | 


--------------------------------------------------------------------------------
/app/containers/ReportBugsPage/styles/index.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   root: {
 5 |     textAlign: `center`,
 6 |     ...mixins({ theme }).center,
 7 |     width: 500,
 8 |     marginTop: 7,
 9 |   },
10 | });
11 | 


--------------------------------------------------------------------------------
/app/containers/Settings/components/SettingsDialogTabContainer.jsx:
--------------------------------------------------------------------------------
 1 | import React, { PureComponent, Fragment } from 'react';
 2 | 
 3 | export default class SettingsDialogTabContainer extends PureComponent {
 4 |   render() {
 5 |     const { children } = this.props;
 6 | 
 7 |     return <Fragment>{children}</Fragment>;
 8 |   }
 9 | }
10 | 


--------------------------------------------------------------------------------
/app/containers/Settings/styles/index.js:
--------------------------------------------------------------------------------
 1 | import { mixins } from '../../../styles/js';
 2 | 
 3 | export const styles = (theme) => ({
 4 |   margin: {},
 5 |   root: {},
 6 |   fieldset: {
 7 |     width: `100%`,
 8 |   },
 9 |   tabHeadingWrapper: {
10 |     borderBottom: `1px solid rgba(0, 123, 255, 0.2)`,
11 |   },
12 |   tab: {
13 |     minWidth: 100,
14 |   },
15 |   tabContainer: {
16 |     paddingTop: 20,
17 |     paddingLeft: 15,
18 |     height: 390,
19 |     overflowX: `auto`,
20 |     overflowY: `auto`,
21 |     borderBottom: `rgba(0, 122, 245, 0.15) 1px solid`,
22 |   },
23 |   subtitleMarginFix: {
24 |     marginTop: 10,
25 |   },
26 |   subtitle: {},
27 |   fmSettingsStylesFix: {
28 |     marginTop: 10,
29 |   },
30 |   subheading: {
31 |     marginBottom: 5,
32 |   },
33 |   title: {
34 |     flex: `0 0 auto`,
35 |     margin: 0,
36 |     padding: `24px 24px 8px`,
37 |   },
38 |   switch: {
39 |     height: 30,
40 |     marginBottom: 7,
41 |   },
42 |   block: {
43 |     marginBottom: 20,
44 |   },
45 |   onboardingPaper: {
46 |     position: `relative`,
47 |     padding: 10,
48 |     marginTop: 4,
49 |     backgroundColor: theme.palette.secondary.main,
50 |   },
51 |   onboardingPaperArrow: {
52 |     fontWeight: `bold`,
53 |     content: ' ',
54 |     borderBottom: `11px solid ${theme.palette.secondary.main}`,
55 |     borderLeft: '8px solid transparent',
56 |     borderRight: '8px solid transparent',
57 |     position: 'absolute',
58 |     top: -10,
59 |     left: 2,
60 |   },
61 |   onboardingPaperBody: {},
62 |   onboardingPaperBodyItem: {
63 |     color: '#ffffff',
64 |     display: 'block',
65 |     width: '100%',
66 |     fontSize: 13,
67 |     fontWeight: 500,
68 |   },
69 | 
70 |   a: {
71 |     fontWeight: `bold`,
72 |   },
73 |   btnPositive: {
74 |     ...mixins({ theme }).btnPositive,
75 |   },
76 | });
77 | 


--------------------------------------------------------------------------------
/app/enums/appUpdater.js:
--------------------------------------------------------------------------------
1 | export const UPDATER_STATUS = {
2 |   inactive: 'inactive',
3 |   checkInProgress: 'checkInProgress',
4 |   updateInProgress: 'updateInProgress',
5 | };
6 | 


--------------------------------------------------------------------------------
/app/enums/index.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * @typedef {object} DEVICE_TYPE
 3 |  * @property {string} mtp - MTP Device
 4 |  * @property {string} local - Local Device
 5 |  * */
 6 | export const DEVICE_TYPE = {
 7 |   mtp: 'mtp',
 8 |   local: 'local',
 9 | };
10 | 
11 | export const MTP_MODE = {
12 |   legacy: 'legacy',
13 |   kalam: 'kalam',
14 | };
15 | 
16 | export const FILE_EXPLORER_VIEW_TYPE = {
17 |   grid: 'grid',
18 |   list: 'list',
19 | };
20 | 
21 | export const APP_THEME_MODE_TYPE = {
22 |   light: 'light',
23 |   dark: 'dark',
24 |   auto: 'auto',
25 | };
26 | 
27 | export const FILE_TRANSFER_DIRECTION = {
28 |   upload: 'upload',
29 |   download: 'download',
30 | };
31 | 
32 | export const USB_HOTPLUG_EVENTS = {
33 |   attach: 'attach',
34 |   detach: 'detach',
35 | };
36 | 


--------------------------------------------------------------------------------
/app/enums/mtpError.js:
--------------------------------------------------------------------------------
 1 | export const MTP_ERROR = {
 2 |   ErrorGeneral: 'ErrorGeneral',
 3 |   ErrorSendObject: 'ErrorSendObject',
 4 |   ErrorFileObjectRead: 'ErrorFileObjectRead',
 5 |   ErrorFileTransfer: 'ErrorFileTransfer',
 6 |   ErrorInvalidPath: 'ErrorInvalidPath',
 7 |   ErrorLocalFileRead: 'ErrorLocalFileRead',
 8 |   ErrorFilePermission: 'ErrorFilePermission',
 9 |   ErrorFileNotFound: 'ErrorFileNotFound',
10 |   ErrorListDirectory: 'ErrorListDirectory',
11 |   ErrorStorageFull: 'ErrorStorageFull',
12 |   ErrorNoStorage: 'ErrorNoStorage',
13 |   ErrorStorageInfo: 'ErrorStorageInfo',
14 |   ErrorDeviceInfo: 'ErrorDeviceInfo',
15 |   ErrorAllowStorageAccess: 'ErrorAllowStorageAccess',
16 |   ErrorMultipleDevice: 'ErrorMultipleDevice',
17 |   ErrorDeviceLocked: 'ErrorDeviceLocked',
18 |   ErrorDeviceSetup: 'ErrorDeviceSetup',
19 |   ErrorDeviceChanged: 'ErrorDeviceChanged',
20 |   ErrorMtpLockExists: 'ErrorMtpLockExists',
21 |   ErrorMtpDetectFailed: 'ErrorMtpDetectFailed',
22 | };
23 | 


--------------------------------------------------------------------------------
/app/helpers/bootHelper.js:
--------------------------------------------------------------------------------
1 | import Boot from '../classes/Boot';
2 | 
3 | export const bootLoader = new Boot();
4 | 


--------------------------------------------------------------------------------
/app/helpers/console.js:
--------------------------------------------------------------------------------
 1 | import clp from 'console-log-plus';
 2 | import { ENV_FLAVOR } from '../constants/env';
 3 | 
 4 | const { warn } = console;
 5 | 
 6 | function logWarning(...warnings) {
 7 |   let showWarning = true;
 8 | 
 9 |   warnings.forEach((warning) => {
10 |     const msg = warning?.toString();
11 | 
12 |     if (msg.includes('UNSAFE_')) showWarning = false;
13 |     else if (msg.includes('SourceMap')) showWarning = false;
14 |     else if (msg.includes('DevTools')) showWarning = false;
15 |   });
16 | 
17 |   if (showWarning) {
18 |     warn(...warnings);
19 |   }
20 | }
21 | 
22 | if (ENV_FLAVOR.disableReactWarnings) {
23 |   console.warn = logWarning;
24 | 
25 |   clp({
26 |     color: 'orange',
27 |     message: `Warning: React depreciation warnings are disabled.\n Edit 'app/helpers/console.js' to enable them`,
28 |   });
29 | }
30 | 


--------------------------------------------------------------------------------
/app/helpers/deviceInfo.js:
--------------------------------------------------------------------------------
 1 | import { IS_RENDERER } from '../constants/env';
 2 | import { isEmpty } from '../utils/funcs';
 3 | 
 4 | export function getDeviceInfo() {
 5 |   if (IS_RENDERER) {
 6 |     // import it here so that the main process doesnt crash
 7 |     // eslint-disable-next-line global-require
 8 |     const { store } = require('../store/configureStore');
 9 |     const state = store?.getState();
10 | 
11 |     if (isEmpty(state)) {
12 |       return {};
13 |     }
14 | 
15 |     const info = state?.Home?.mtpDevice?.info?.mtpDeviceInfo;
16 | 
17 |     if (isEmpty(info)) {
18 |       return {};
19 |     }
20 | 
21 |     const {
22 |       StandardVersion,
23 |       MTPVersion,
24 |       MTPExtension,
25 |       Manufacturer,
26 |       Model,
27 |       DeviceVersion,
28 |     } = info;
29 | 
30 |     return {
31 |       StandardVersion,
32 |       MTPVersion,
33 |       MTPExtension,
34 |       Manufacturer,
35 |       Model,
36 |       DeviceVersion,
37 |     };
38 |   }
39 | 
40 |   return {};
41 | }
42 | 


--------------------------------------------------------------------------------
/app/helpers/fileOps.js:
--------------------------------------------------------------------------------
 1 | import {
 2 |   existsSync as _existsSync,
 3 |   writeFile as _writeFileAsync,
 4 |   appendFile as _appendFileAsync,
 5 |   readFileSync as _readFileSync,
 6 |   writeFileSync as _writeFileSync,
 7 | } from 'fs';
 8 | import { EOL } from 'os';
 9 | import mkdirp from 'mkdirp';
10 | import rimraf from 'rimraf';
11 | 
12 | export const writeFileAsync = (filePath, text) => {
13 |   const options = { mode: 0o755 };
14 | 
15 |   _writeFileAsync(filePath, text, options, (err) => {
16 |     if (err) {
17 |       console.error(err, `writeFileAsync`);
18 | 
19 |       return null;
20 |     }
21 |   });
22 | };
23 | 
24 | export const writeFileSync = (filePath, text) => {
25 |   const options = { mode: 0o755 };
26 | 
27 |   try {
28 |     _writeFileSync(filePath, text, options);
29 |   } catch (err) {
30 |     console.error(err, `writeFileSync`);
31 |   }
32 | };
33 | 
34 | export const appendFileAsync = (filePath, text) => {
35 |   const options = { mode: 0o755 };
36 | 
37 |   _appendFileAsync(filePath, text + EOL, options, (err) => {
38 |     if (err) {
39 |       console.error(err, `appendFileAsync`);
40 | 
41 |       return null;
42 |     }
43 |   });
44 | };
45 | 
46 | export const readFileSync = (filePath) => {
47 |   const options = { encoding: 'utf8' };
48 | 
49 |   return _readFileSync(filePath, options);
50 | };
51 | 
52 | export const fileExistsSync = (filePath) => _existsSync(filePath);
53 | 
54 | export const createDirSync = async (newFolderPath) => {
55 |   await mkdirp.sync(newFolderPath);
56 | };
57 | 
58 | export const deleteFilesSync = (filePath) => {
59 |   rimraf.sync(filePath);
60 | };
61 | 


--------------------------------------------------------------------------------
/app/helpers/identifiers.js:
--------------------------------------------------------------------------------
 1 | import { v6 as uuidv6 } from 'uuid';
 2 | 
 3 | import { identifierStorage } from './storageHelper';
 4 | import { isEmpty } from '../utils/funcs';
 5 | 
 6 | export function getMachineId() {
 7 |   try {
 8 |     const settings = identifierStorage.getItems(['machineId']);
 9 | 
10 |     if (!settings?.machineId || isEmpty(settings?.machineId)) {
11 |       const _machineId = uuidv6();
12 | 
13 |       identifierStorage.setItems({
14 |         machineId: _machineId,
15 |       });
16 | 
17 |       return _machineId;
18 |     }
19 | 
20 |     return settings.machineId;
21 |   } catch (e) {
22 |     console.error(`Unable to find machineId. Error: ${e}`);
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/app/helpers/logs.js:
--------------------------------------------------------------------------------
 1 | import { PATHS } from '../constants/paths';
 2 | import { undefinedOrNull } from '../utils/funcs';
 3 | 
 4 | /**
 5 |  * Description - Strip user home directory path from the error before it is sent to sentry
 6 |  * @param s
 7 |  * @return {string|string}
 8 |  */
 9 | export const redactHomeDirectory = (s) => {
10 |   if (undefinedOrNull(s)) {
11 |     return '';
12 |   }
13 | 
14 |   return (
15 |     s?.toString()?.replaceAll(new RegExp(PATHS.homeDir, 'ig'), '/Users/user') ??
16 |     ''
17 |   );
18 | };
19 | 


--------------------------------------------------------------------------------
/app/helpers/reducerPrefixer.js:
--------------------------------------------------------------------------------
1 | export default (prefix, typesList) => {
2 |   return typesList.reduce((result, value) => {
3 |     // eslint-disable-next-line no-param-reassign
4 |     result[value] = `${prefix}/${value}`;
5 | 
6 |     return result;
7 |   }, {});
8 | };
9 | 


--------------------------------------------------------------------------------
/app/helpers/remoteWindowHelpers.js:
--------------------------------------------------------------------------------
 1 | import { IS_RENDERER } from '../constants/env';
 2 | 
 3 | export const getRemoteWindow = () => {
 4 |   let remote;
 5 | 
 6 |   if (IS_RENDERER) {
 7 |     remote = window.require('@electron/remote');
 8 |   } else {
 9 |     // eslint-disable-next-line global-require
10 |     remote = require('@electron/remote/main');
11 |   }
12 | 
13 |   return remote;
14 | };
15 | 


--------------------------------------------------------------------------------
/app/helpers/settings.js:
--------------------------------------------------------------------------------
 1 | import { settingsStorage } from './storageHelper';
 2 | import { getAppThemeMode } from './theme';
 3 | import { isPrereleaseVersion, undefinedOrNull } from '../utils/funcs';
 4 | import { initialState } from '../containers/Settings/reducers';
 5 | import { checkIf } from '../utils/checkIf';
 6 | import { FILE_TRANSFER_DIRECTION } from '../enums';
 7 | 
 8 | export const getAppThemeModeSetting = () => {
 9 |   const setting = settingsStorage.getItems(['appThemeMode']);
10 | 
11 |   let value = setting.appThemeMode;
12 | 
13 |   if (undefinedOrNull(value)) {
14 |     value = initialState.appThemeMode;
15 |   }
16 | 
17 |   return getAppThemeMode(value);
18 | };
19 | 
20 | export const getMtpModeSetting = () => {
21 |   const setting = settingsStorage.getItems(['mtpMode']);
22 | 
23 |   let value = setting.mtpMode;
24 | 
25 |   if (undefinedOrNull(value)) {
26 |     value = initialState.mtpMode;
27 |   }
28 | 
29 |   return value;
30 | };
31 | 
32 | export const getFilesPreprocessingBeforeTransferSetting = ({ direction }) => {
33 |   checkIf(direction, 'string');
34 |   checkIf(direction, 'inObjectValues', FILE_TRANSFER_DIRECTION);
35 | 
36 |   const setting = settingsStorage.getItems([
37 |     'filesPreprocessingBeforeTransfer',
38 |   ]);
39 | 
40 |   let value = setting.filesPreprocessingBeforeTransfer
41 |     ? setting.filesPreprocessingBeforeTransfer[direction]
42 |     : null;
43 | 
44 |   if (undefinedOrNull(value)) {
45 |     value = initialState.filesPreprocessingBeforeTransfer[direction];
46 |   }
47 | 
48 |   checkIf(value, 'boolean');
49 | 
50 |   return value;
51 | };
52 | 
53 | export const getEnablePrereleaseUpdatesSetting = () => {
54 |   const setting = settingsStorage.getItems(['enablePrereleaseUpdates']);
55 | 
56 |   let value = setting.enablePrereleaseUpdates;
57 | 
58 |   const isPrerelease = isPrereleaseVersion();
59 | 
60 |   if (isPrerelease) {
61 |     return true;
62 |   }
63 | 
64 |   if (undefinedOrNull(value)) {
65 |     value = initialState.enablePrereleaseUpdates;
66 |   }
67 | 
68 |   return value;
69 | };
70 | 


--------------------------------------------------------------------------------
/app/helpers/storageHelper.js:
--------------------------------------------------------------------------------
1 | import { PATHS } from '../constants/paths';
2 | import Storage from '../classes/Storage';
3 | 
4 | const { settingsFile, identifierFile } = PATHS;
5 | 
6 | export const identifierStorage = new Storage(identifierFile, true);
7 | 
8 | export const settingsStorage = new Storage(settingsFile, false);
9 | 


--------------------------------------------------------------------------------
/app/helpers/theme.js:
--------------------------------------------------------------------------------
 1 | import { nativeTheme } from 'electron';
 2 | import { APP_THEME_MODE_TYPE } from '../enums';
 3 | import { undefinedOrNull } from '../utils/funcs';
 4 | import { getAppThemeModeSetting } from './settings';
 5 | import { getRemoteWindow } from './remoteWindowHelpers';
 6 | 
 7 | const remote = getRemoteWindow();
 8 | 
 9 | // [appThemeModeSettings] is optional
10 | // if [appThemeModeSettings] is not provided then fetch the theme value from the settings
11 | export const getAppThemeMode = (appThemeModeSettings) => {
12 |   // compatible with both renderer and main process
13 |   const { shouldUseDarkColors } = remote?.nativeTheme ?? nativeTheme ?? {};
14 | 
15 |   let _appThemeModeSettings = appThemeModeSettings;
16 | 
17 |   if (undefinedOrNull(_appThemeModeSettings)) {
18 |     _appThemeModeSettings = getAppThemeModeSetting();
19 |   }
20 | 
21 |   switch (_appThemeModeSettings) {
22 |     case APP_THEME_MODE_TYPE.dark:
23 |       return _appThemeModeSettings;
24 | 
25 |     case APP_THEME_MODE_TYPE.light:
26 |       return _appThemeModeSettings;
27 | 
28 |     default:
29 |       if (shouldUseDarkColors) {
30 |         return APP_THEME_MODE_TYPE.dark;
31 |       }
32 | 
33 |       return APP_THEME_MODE_TYPE.light;
34 |   }
35 | };
36 | 
37 | export const getContrastingTheme = (appThemeMode) => {
38 |   if (appThemeMode === APP_THEME_MODE_TYPE.dark) {
39 |     return APP_THEME_MODE_TYPE.light;
40 |   }
41 | 
42 |   return APP_THEME_MODE_TYPE.dark;
43 | };
44 | 


--------------------------------------------------------------------------------
/app/helpers/titlebarDoubleClick.js:
--------------------------------------------------------------------------------
 1 | import { getRemoteWindow } from './remoteWindowHelpers';
 2 | 
 3 | const remote = getRemoteWindow();
 4 | 
 5 | export const toggleWindowSizeOnDoubleClick = () => {
 6 |   const window = remote.getCurrentWindow();
 7 | 
 8 |   if (!window.isMaximized()) {
 9 |     window.maximize();
10 | 
11 |     return null;
12 |   }
13 | 
14 |   window.unmaximize();
15 | };
16 | 


--------------------------------------------------------------------------------
/app/helpers/windowHelper.js:
--------------------------------------------------------------------------------
 1 | import { BrowserWindow } from 'electron';
 2 | import { urls } from 'nice-utils';
 3 | import { getAppThemeMode } from './theme';
 4 | import { getCurrentThemePalette } from '../containers/App/styles';
 5 | import { undefinedOrNull } from '../utils/funcs';
 6 | import { IS_RENDERER } from '../constants/env';
 7 | import { getRemoteWindow } from './remoteWindowHelpers';
 8 | 
 9 | const remote = getRemoteWindow();
10 | 
11 | export const getMainWindowMainProcess = () => {
12 |   const _mainWindow = BrowserWindow.getAllWindows();
13 | 
14 |   if (typeof _mainWindow === 'undefined' || _mainWindow === null) {
15 |     return null;
16 |   }
17 | 
18 |   return BrowserWindow.getAllWindows()[_mainWindow.length - 1];
19 | };
20 | 
21 | export const getMainWindowRendererProcess = () => {
22 |   const _mainWindow = remote.BrowserWindow.getAllWindows();
23 | 
24 |   if (typeof _mainWindow === 'undefined' || _mainWindow === null) {
25 |     return null;
26 |   }
27 | 
28 |   return remote.BrowserWindow.getAllWindows()[_mainWindow.length - 1];
29 | };
30 | 
31 | export const getWindowBackgroundColor = () => {
32 |   const appThemeMode = getAppThemeMode();
33 |   const { background } = getCurrentThemePalette(appThemeMode);
34 | 
35 |   return background.paper;
36 | };
37 | 
38 | export const getCurrentWindowHash = () => {
39 |   if (!IS_RENDERER) {
40 |     return null;
41 |   }
42 | 
43 |   const hash = urls().getHash();
44 | 
45 |   if (undefinedOrNull(hash) || hash === '') {
46 |     return '/';
47 |   }
48 | 
49 |   return hash;
50 | };
51 | 


--------------------------------------------------------------------------------
/app/index.js:
--------------------------------------------------------------------------------
 1 | /* eslint global-require: off */
 2 | 
 3 | import './services/sentry';
 4 | 
 5 | import React from 'react';
 6 | import { render } from 'react-dom';
 7 | import Root from './containers/App/Root';
 8 | import { history, store } from './store/configureStore';
 9 | import './styles/scss/app.global.scss';
10 | 
11 | const MOUNT_POINT = document.getElementById('root');
12 | 
13 | render(<Root store={store} history={history} />, MOUNT_POINT);
14 | 


--------------------------------------------------------------------------------
/app/public/images/FileExplorer/buymeacoffee-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/FileExplorer/buymeacoffee-button.png


--------------------------------------------------------------------------------
/app/public/images/FileExplorer/folder-dark.svg:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="iso-8859-1"?>
 2 | <!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
 3 | <svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 4 | 	 viewBox="0 0 408 408" style="enable-background:new 0 0 408 408;" xml:space="preserve">
 5 | <g>
 6 | 	<g>
 7 | 		<path d="M332,121.921H184.8l-29.28-34.8c-0.985-1.184-2.461-1.848-4-1.8H32.76C14.628,85.453,0,100.189,0,118.321v214.04
 8 | 			c0.022,18.194,14.766,32.938,32.96,32.96H332c18.194-0.022,32.938-14.766,32.96-32.96v-177.48
 9 | 			C364.938,136.687,350.194,121.943,332,121.921z"/>
10 | 	</g>
11 | </g>
12 | <g>
13 | 	<g>
14 | 		<path d="M375.24,79.281H228l-29.28-34.8c-0.985-1.184-2.461-1.848-4-1.8H76c-16.452,0.027-30.364,12.181-32.6,28.48h108.28
15 | 			c5.678-0.014,11.069,2.492,14.72,6.84l25,29.72H332c26.005,0.044,47.076,21.115,47.12,47.12v167.52
16 | 			c16.488-2.057,28.867-16.064,28.88-32.68v-177.48C407.957,94.1,393.34,79.413,375.24,79.281z"/>
17 | 	</g>
18 | </g>
19 | <g>
20 | </g>
21 | <g>
22 | </g>
23 | <g>
24 | </g>
25 | <g>
26 | </g>
27 | <g>
28 | </g>
29 | <g>
30 | </g>
31 | <g>
32 | </g>
33 | <g>
34 | </g>
35 | <g>
36 | </g>
37 | <g>
38 | </g>
39 | <g>
40 | </g>
41 | <g>
42 | </g>
43 | <g>
44 | </g>
45 | <g>
46 | </g>
47 | <g>
48 | </g>
49 | </svg>
50 | 


--------------------------------------------------------------------------------
/app/public/images/FileExplorer/folder-light.svg:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0"?>
 2 | <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.com/svgjs" version="1.1" width="512" height="512" x="0" y="0" viewBox="0 0 408 408" style="enable-background:new 0 0 512 512" xml:space="preserve" class=""><g>
 3 | <g xmlns="http://www.w3.org/2000/svg">
 4 | 	<g>
 5 | 		<path d="M332,121.921H184.8l-29.28-34.8c-0.985-1.184-2.461-1.848-4-1.8H32.76C14.628,85.453,0,100.189,0,118.321v214.04    c0.022,18.194,14.766,32.938,32.96,32.96H332c18.194-0.022,32.938-14.766,32.96-32.96v-177.48    C364.938,136.687,350.194,121.943,332,121.921z" fill="#ffffff" data-original="#000000" style=""/>
 6 | 	</g>
 7 | </g>
 8 | <g xmlns="http://www.w3.org/2000/svg">
 9 | 	<g>
10 | 		<path d="M375.24,79.281H228l-29.28-34.8c-0.985-1.184-2.461-1.848-4-1.8H76c-16.452,0.027-30.364,12.181-32.6,28.48h108.28    c5.678-0.014,11.069,2.492,14.72,6.84l25,29.72H332c26.005,0.044,47.076,21.115,47.12,47.12v167.52    c16.488-2.057,28.867-16.064,28.88-32.68v-177.48C407.957,94.1,393.34,79.413,375.24,79.281z" fill="#ffffff" data-original="#000000" style=""/>
11 | 	</g>
12 | </g>
13 | <g xmlns="http://www.w3.org/2000/svg">
14 | </g>
15 | <g xmlns="http://www.w3.org/2000/svg">
16 | </g>
17 | <g xmlns="http://www.w3.org/2000/svg">
18 | </g>
19 | <g xmlns="http://www.w3.org/2000/svg">
20 | </g>
21 | <g xmlns="http://www.w3.org/2000/svg">
22 | </g>
23 | <g xmlns="http://www.w3.org/2000/svg">
24 | </g>
25 | <g xmlns="http://www.w3.org/2000/svg">
26 | </g>
27 | <g xmlns="http://www.w3.org/2000/svg">
28 | </g>
29 | <g xmlns="http://www.w3.org/2000/svg">
30 | </g>
31 | <g xmlns="http://www.w3.org/2000/svg">
32 | </g>
33 | <g xmlns="http://www.w3.org/2000/svg">
34 | </g>
35 | <g xmlns="http://www.w3.org/2000/svg">
36 | </g>
37 | <g xmlns="http://www.w3.org/2000/svg">
38 | </g>
39 | <g xmlns="http://www.w3.org/2000/svg">
40 | </g>
41 | <g xmlns="http://www.w3.org/2000/svg">
42 | </g>
43 | </g></svg>
44 | 


--------------------------------------------------------------------------------
/app/public/images/FileExplorer/paypal-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/FileExplorer/paypal-logo.png


--------------------------------------------------------------------------------
/app/public/images/file-types/7z.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><path style="fill:#90bae1;fill-opacity:1" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/><g><path style="fill:#c8bdb8" d="M28.5,24v-2h2v-2h-2v-2h2v-2h-2v-2h2v-2h-2v-2h2V8h-2V6h-2v2h-2v2h2v2h-2v2h2v2h-2v2h2v2h-2v2h2v2 h-4v5c0,2.757,2.243,5,5,5s5-2.243,5-5v-5H28.5z M30.5,29c0,1.654-1.346,3-3,3s-3-1.346-3-3v-3h6V29z"/><path style="fill:#c8bdb8" d="M26.5,30h2c0.552,0,1-0.447,1-1s-0.448-1-1-1h-2c-0.552,0-1,0.447-1,1S25.948,30,26.5,30z"/></g></g><g transform="scale(0.99005755,1.0100423)" style="font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:13.88808155px;font-family:Allerta;-inkscape-font-specification:Allerta;fill:#fff;fill-opacity:1"><path d="m 22.232274,52.472202 3.47202,-8.666488 -4.353588,0 0,-1.329133 6.279474,0 -3.878897,9.995621 -1.519009,0 z" style="fill:#fff"/><path d="m 29.393316,44.822907 5.818346,0 0,1.315571 -3.933148,4.801153 -0.271251,0.217001 4.204399,0 0,1.31557 -5.818346,0 0,-1.31557 3.933148,-4.801153 0.271251,-0.217001 -4.204399,0 0,-1.315571 z" style="fill:#fff"/></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/ai.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><path style="fill:#ffc14f" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/><g><path style="fill:#fff" d="M20.067,53l3.527-10.063h1.627L28.722,53h-1.695l-0.725-2.092h-3.787L21.776,53H20.067z M22.897,49.801h3.008l-1.49-4.348L22.897,49.801z"/><path style="fill:#fff" d="M32.536,53h-1.668V42.924h1.668V53z"/></g><path style="fill:#c8bdb8" d="M37.5,11v0.461c-3.071,0.968-5.503,3.382-6.502,6.44C30.311,17.346,29.45,17,28.5,17 c-1.859,0-3.411,1.28-3.858,3H21.5v-2h-6v6h6v-2h2.921c-0.336,2.663-1.985,4.978-4.389,6.163C19.364,26.884,18.04,26,16.5,26 c-2.206,0-4,1.794-4,4s1.794,4,4,4c2.146,0,3.888-1.702,3.982-3.825c2.655-1.151,4.647-3.387,5.524-6.073 C26.692,24.655,27.552,25,28.5,25c1.859,0,3.411-1.28,3.858-3H35.5v2h6v-6h-6v2h-2.931c0.379-3.019,2.444-5.514,5.222-6.518 C38.383,14.955,39.818,16,41.5,16c2.206,0,4-1.794,4-4v-1H37.5z M19.5,22h-2v-2h2V22z M16.5,32c-1.103,0-2-0.897-2-2s0.897-2,2-2 s2,0.897,2,2S17.603,32,16.5,32z M37.5,20h2v2h-2V20z M28.5,23c-1.103,0-2-0.897-2-2s0.897-2,2-2s2,0.897,2,2S29.603,23,28.5,23z M41.5,14c-0.723,0-1.353-0.389-1.704-0.964C40.028,13.015,40.262,13,40.5,13h2.731C42.886,13.597,42.239,14,41.5,14z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/archive.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><g><rect x="26.5" y="42" style="fill:#c8bdb8" width="2" height="14"/><polygon style="fill:#c8bdb8" points="30.5,23 30.5,21 28.5,21 28.5,19 26.5,19 26.5,21 24.5,21 24.5,23 26.5,23 26.5,25 24.5,25 24.5,27 26.5,27 26.5,29 24.5,29 24.5,31 26.5,31 26.5,34 28.5,34 28.5,31 30.5,31 30.5,29 28.5,29 28.5,27 30.5,27 30.5,25 28.5,25 28.5,23"/></g><g><rect x="23.5" y="34" style="fill:#cbb292" width="8" height="8"/><path style="fill:#5e5f62" d="M32.5,43h-10V33h10V43z M24.5,41h6v-6h-6V41z"/></g><rect x="23.5" y="36" style="fill:#5e5f62" width="8" height="2"/></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/audio.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><path style="fill:#c8bdb8" d="M 35.67,26.986 C 35.103,26.19 34.37,25.443 33.362,24.635 29.448,21.504 28.605,18.358 28.5,17.897 L 28.5,17 c 0,-0.553 -0.447,-1 -1,-1 -0.553,0 -1,0.447 -1,1 l 0,1 0,8.359 0,9.053 -3.706,0 c -3.882,0 -6.294,1.961 -6.294,5.117 0,3.466 2.24,5.706 5.706,5.706 3.471,0 6.294,-2.823 6.294,-6.294 l 0,-11.473 0.298,0.243 c 0.34,0.336 0.861,0.72 1.521,1.205 2.318,1.709 6.2,4.567 5.224,7.793 C 35.514,37.807 35.5,37.904 35.5,38 c 0,0.43 0.278,0.826 0.71,0.957 0.097,0.029 0.194,0.043 0.29,0.043 0.43,0 0.826,-0.278 0.957,-0.71 C 39.084,32.915 37.035,28.9 35.67,26.986 Z M 26.5,39.941 c 0,2.368 -1.926,4.294 -4.294,4.294 -2.355,0 -3.706,-1.351 -3.706,-3.706 0,-2.576 2.335,-3.117 4.294,-3.117 l 3.706,0 0,2.529 z M 31.505,28.308 C 30.934,27.886 30.44,27.523 30.134,27.227 l -1.634,-1.34 0,-3.473 c 0.827,1.174 1.987,2.483 3.612,3.783 0.858,0.688 1.472,1.308 1.929,1.95 0.716,1.003 1.431,2.339 1.788,3.978 -1.327,-1.61 -3.084,-2.904 -4.324,-3.817 z"/></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/avi.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><path style="fill:#d75e72" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/><g><path style="fill:#fff" d="M16.361,53l3.527-10.063h1.627L25.016,53H23.32l-0.725-2.092h-3.787L18.07,53H16.361z M19.191,49.801h3.008l-1.49-4.348L19.191,49.801z"/><path style="fill:#fff" d="M29.828,53.055l-3.131-10.131h1.873l2.338,8.695l2.475-8.695h1.859l-3.281,10.131H29.828z"/><path style="fill:#fff" d="M38.988,53H37.32V42.924h1.668V53z"/></g><polygon style="fill:#c8bdb8" points="23.5,28 23.5,20.954 23.5,14 34.5,21"/></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/exe.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><path style="fill:#9777a8" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/><g><path style="fill:#fff" d="M17.082,44.168v3.172h4.211v1.121h-4.211v3.295h4.635V53h-6.303V42.924h6.303v1.244H17.082z"/><path style="fill:#fff" d="M28.58,48.105L31.137,53h-1.9l-1.6-3.801H27.5L25.777,53h-1.9l2.557-4.895l-2.721-5.182h1.873 l1.777,4.102H27.5l1.928-4.102h1.873L28.58,48.105z"/><path style="fill:#fff" d="M35.266,44.168v3.172h4.211v1.121h-4.211v3.295H39.9V53h-6.303V42.924H39.9v1.244H35.266z"/></g><path style="fill:#9777a8" d="M33.5,32c-0.099,0-0.2-0.015-0.299-0.046c-0.527-0.165-0.821-0.726-0.656-1.253l5-16 c0.165-0.527,0.726-0.821,1.253-0.656c0.527,0.165,0.821,0.726,0.656,1.253l-5,16C34.321,31.726,33.926,32,33.5,32z"/><circle style="fill:#9777a8" cx="29" cy="19.5" r="1.5"/><circle style="fill:#9777a8" cx="29" cy="26.5" r="1.5"/><path style="fill:#9777a8" d="M23.5,30h-2c-3.86,0-7-3.14-7-7s3.14-7,7-7h2c0.552,0,1,0.448,1,1s-0.448,1-1,1h-2 c-2.757,0-5,2.243-5,5s2.243,5,5,5h2c0.552,0,1,0.448,1,1S24.052,30,23.5,30z"/></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/fla.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><path style="fill:#ce3c3b" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/><g><path style="fill:#fff" d="M17.246,44.168v3.172h4.211v1.121h-4.211V53h-1.668V42.924h6.303v1.244H17.246z"/><path style="fill:#fff" d="M25.299,42.924v8.832h4.635V53h-6.303V42.924H25.299z"/><path style="fill:#fff" d="M31.205,53l3.527-10.063h1.627L39.859,53h-1.695l-0.725-2.092h-3.787L32.914,53H31.205z M34.035,49.801h3.008l-1.49-4.348L34.035,49.801z"/></g><circle style="fill:#c8bdb8" cx="25.5" cy="16" r="2"/><g><path style="fill:#c8bdb8" d="M34.985,13.929l-0.707-0.707C32.201,11.144,29.438,10,26.5,10s-5.701,1.144-7.778,3.222 C16.644,15.299,15.5,18.062,15.5,21s1.144,5.701,3.222,7.778C20.799,30.856,23.562,32,26.5,32s5.701-1.144,7.778-3.222 l0.707-0.707L27.914,21L34.985,13.929z M32.118,28.032C30.528,29.308,28.567,30,26.5,30c-2.404,0-4.664-0.936-6.364-2.636 S17.5,23.404,17.5,21s0.936-4.664,2.636-6.364S24.096,12,26.5,12c2.067,0,4.028,0.692,5.618,1.968L25.086,21L32.118,28.032z"/><path style="fill:#c8bdb8" d="M35.5,20h-3c-0.553,0-1,0.447-1,1s0.447,1,1,1h3c0.553,0,1-0.447,1-1S36.053,20,35.5,20z"/><path style="fill:#c8bdb8" d="M41.5,20h-2c-0.553,0-1,0.447-1,1s0.447,1,1,1h2c0.553,0,1-0.447,1-1S42.053,20,41.5,20z"/></g></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/html.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><path style="fill:#ec6630" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/><g><path style="fill:#fff" d="M17.455,42.924V53h-1.641v-4.539h-4.361V53H9.785V42.924h1.668v4.416h4.361v-4.416H17.455z"/><path style="fill:#fff" d="M27.107,42.924v1.121H24.1V53h-1.654v-8.955h-3.008v-1.121H27.107z"/><path style="fill:#fff" d="M36.705,42.924h1.668V53h-1.668v-6.932l-2.256,5.605H33l-2.27-5.605V53h-1.668V42.924h1.668 l2.994,6.891L36.705,42.924z"/><path style="fill:#fff" d="M42.57,42.924v8.832h4.635V53h-6.303V42.924H42.57z"/></g><g><path style="fill:#ec6630" d="M23.207,16.293c-0.391-0.391-1.023-0.391-1.414,0l-6,6c-0.391,0.391-0.391,1.023,0,1.414l6,6 C21.988,29.902,22.244,30,22.5,30s0.512-0.098,0.707-0.293c0.391-0.391,0.391-1.023,0-1.414L17.914,23l5.293-5.293 C23.598,17.316,23.598,16.684,23.207,16.293z"/><path style="fill:#ec6630" d="M41.207,22.293l-6-6c-0.391-0.391-1.023-0.391-1.414,0s-0.391,1.023,0,1.414L39.086,23 l-5.293,5.293c-0.391,0.391-0.391,1.023,0,1.414C33.988,29.902,34.244,30,34.5,30s0.512-0.098,0.707-0.293l6-6 C41.598,23.316,41.598,22.684,41.207,22.293z"/></g></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/tiff.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><path style="fill:#556080;fill-opacity:1" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><circle style="fill:#f3d55b" cx="18.931" cy="14.431" r="4.569"/><polygon style="fill:#8d97b3;fill-opacity:1" points="6.5,39 17.5,39 49.5,39 49.5,28 39.5,18.5 29,30 23.517,24.517"/></g><g transform="scale(0.99005755,1.0100423)" style="font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:13.88808155px;font-family:Allerta;-inkscape-font-specification:Allerta;fill:#fff;fill-opacity:1"><path d="m 21.859303,42.442173 0,1.112131 -2.983768,0 0,8.88349 -1.641072,0 0,-8.88349 -2.983768,0 0,-1.112131 7.608608,0 z" style="fill:#fff"/><path d="m 25.494074,52.437794 -1.654634,0 0,-9.995621 1.654634,0 0,9.995621 z" style="fill:#fff"/><path d="m 29.684912,43.676367 0,3.146519 4.177274,0 0,1.112131 -4.177274,0 0,4.502777 -1.654635,0 0,-9.995621 6.252349,0 0,1.234194 -4.597714,0 z" style="fill:#fff"/><path d="m 37.71396,43.676367 0,3.146519 4.177274,0 0,1.112131 -4.177274,0 0,4.502777 -1.654635,0 0,-9.995621 6.252349,0 0,1.234194 -4.597714,0 z" style="fill:#fff"/></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/unknown.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><path style="fill:#c8bdb8" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/><circle style="fill:#fff" cx="18.5" cy="47" r="3"/><circle style="fill:#fff" cx="28.5" cy="47" r="3"/><circle style="fill:#fff" cx="38.5" cy="47" r="3"/></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/video.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><path style="fill:#c8bdb8" d="M 24.5,40 C 24.334,40 24.169,39.959 24.019,39.877 23.699,39.701 23.5,39.365 23.5,39 l 0,-14 c 0,-0.365 0.199,-0.701 0.519,-0.877 0.321,-0.175 0.71,-0.162 1.019,0.033 l 11,7 C 36.325,31.34 36.5,31.658 36.5,32 c 0,0.342 -0.175,0.66 -0.463,0.844 l -11,7 C 24.874,39.947 24.687,40 24.5,40 Z m 1,-13.179 0,10.357 L 33.637,32 25.5,26.821 Z"/><path style="fill:#c8bdb8" d="m 28.5,47 c -8.271,0 -15,-6.729 -15,-15 0,-8.271 6.729,-15 15,-15 8.271,0 15,6.729 15,15 0,8.271 -6.729,15 -15,15 z m 0,-28 c -7.168,0 -13,5.832 -13,13 0,7.168 5.832,13 13,13 7.168,0 13,-5.832 13,-13 0,-7.168 -5.832,-13 -13,-13 z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/></g></svg>


--------------------------------------------------------------------------------
/app/public/images/file-types/zip.svg:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="iso-8859-1"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 56 56" style="enable-background:new 0 0 56 56" xml:space="preserve"><g><path style="fill:#e9e9e0" d="M36.985,0H7.963C7.155,0,6.5,0.655,6.5,1.926V55c0,0.345,0.655,1,1.463,1h40.074 c0.808,0,1.463-0.655,1.463-1V12.978c0-0.696-0.093-0.92-0.257-1.085L37.607,0.257C37.442,0.093,37.218,0,36.985,0z"/><polygon style="fill:#d9d7ca" points="37.5,0.151 37.5,12 49.349,12"/><path style="fill:#556080" d="M48.037,56H7.963C7.155,56,6.5,55.345,6.5,54.537V39h43v15.537C49.5,55.345,48.845,56,48.037,56z"/><g><path style="fill:#fff" d="M25.266,42.924v1.326l-4.799,7.205l-0.273,0.219h5.072V53h-6.699v-1.326l4.799-7.205l0.287-0.219 h-5.086v-1.326H25.266z"/><path style="fill:#fff" d="M29.271,53h-1.668V42.924h1.668V53z"/><path style="fill:#fff" d="M33.414,53h-1.641V42.924h2.898c0.428,0,0.852,0.068,1.271,0.205 c0.419,0.137,0.795,0.342,1.128,0.615c0.333,0.273,0.602,0.604,0.807,0.991s0.308,0.822,0.308,1.306 c0,0.511-0.087,0.973-0.26,1.388c-0.173,0.415-0.415,0.764-0.725,1.046c-0.31,0.282-0.684,0.501-1.121,0.656 s-0.921,0.232-1.449,0.232h-1.217V53z M33.414,44.168v3.992h1.504c0.2,0,0.398-0.034,0.595-0.103 c0.196-0.068,0.376-0.18,0.54-0.335s0.296-0.371,0.396-0.649c0.1-0.278,0.15-0.622,0.15-1.032c0-0.164-0.023-0.354-0.068-0.567 c-0.046-0.214-0.139-0.419-0.28-0.615c-0.142-0.196-0.34-0.36-0.595-0.492c-0.255-0.132-0.593-0.198-1.012-0.198H33.414z"/></g><g><path style="fill:#c8bdb8" d="M28.5,24v-2h2v-2h-2v-2h2v-2h-2v-2h2v-2h-2v-2h2V8h-2V6h-2v2h-2v2h2v2h-2v2h2v2h-2v2h2v2h-2v2h2v2 h-4v5c0,2.757,2.243,5,5,5s5-2.243,5-5v-5H28.5z M30.5,29c0,1.654-1.346,3-3,3s-3-1.346-3-3v-3h6V29z"/><path style="fill:#c8bdb8" d="M26.5,30h2c0.552,0,1-0.447,1-1s-0.448-1-1-1h-2c-0.552,0-1,0.447-1,1S25.948,30,26.5,30z"/></g></g></svg>


--------------------------------------------------------------------------------
/app/public/images/help/allow-data-access.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/allow-data-access.png


--------------------------------------------------------------------------------
/app/public/images/help/charge-only-permission.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/charge-only-permission.png


--------------------------------------------------------------------------------
/app/public/images/help/full-disk-access-file-picker.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/full-disk-access-file-picker.jpeg


--------------------------------------------------------------------------------
/app/public/images/help/full-disk-access.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/full-disk-access.png


--------------------------------------------------------------------------------
/app/public/images/help/google-drive-not-connecting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/google-drive-not-connecting.png


--------------------------------------------------------------------------------
/app/public/images/help/macos-directory-access.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/macos-directory-access.jpg


--------------------------------------------------------------------------------
/app/public/images/help/privacy-restricted-folder-access.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/privacy-restricted-folder-access.png


--------------------------------------------------------------------------------
/app/public/images/help/sleep-setting.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/sleep-setting.jpg


--------------------------------------------------------------------------------
/app/public/images/help/transfer-media-permission.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/transfer-media-permission.png


--------------------------------------------------------------------------------
/app/public/images/help/usb-notification-charging-via-usb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/usb-notification-charging-via-usb.png


--------------------------------------------------------------------------------
/app/public/images/help/usb-notification-transferring-media.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/help/usb-notification-transferring-media.png


--------------------------------------------------------------------------------
/app/public/images/no-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/no-image.png


--------------------------------------------------------------------------------
/app/public/images/toolbar/buymeacoffee.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/app/public/images/toolbar/buymeacoffee.png


--------------------------------------------------------------------------------
/app/services/ipc-events/IpcEventHandler.js:
--------------------------------------------------------------------------------
 1 | import { ipcMain } from 'electron';
 2 | import { IpcEvents } from './IpcEventType';
 3 | import {
 4 |   faqsWindow,
 5 |   helpPhoneNotConnectingWindow,
 6 |   privacyPolicyWindow,
 7 |   reportBugsWindow,
 8 | } from '../../helpers/createWindows';
 9 | 
10 | export default class IpcEventService {
11 |   static shared = new IpcEventService();
12 | 
13 |   start() {
14 |     this.#init();
15 |   }
16 | 
17 |   #init = () => {
18 |     // todo move all create window methods to IpcEventService and all window create methods from renderer should be event-driven (aka via IpcEventService). The main process windows could be directly invoked.
19 |     //  This is done to avoid issues with 'electron/remote' (in the packaged builds the electron/remote enable doesn't work)
20 | 
21 |     ipcMain.on(IpcEvents.OPEN_FAQS_WINDOW, (_, __) => {
22 |       faqsWindow(false);
23 |     });
24 |     ipcMain.on(IpcEvents.OPEN_HELP_PHONE_NOT_CONNECTING_WINDOW, (_, __) => {
25 |       helpPhoneNotConnectingWindow(false);
26 |     });
27 |     ipcMain.on(IpcEvents.OPEN_HELP_PRIVACY_POLICY_WINDOW, (_, __) => {
28 |       privacyPolicyWindow(false);
29 |     });
30 | 
31 |     ipcMain.on(IpcEvents.REPORT_BUGS_DISPOSE_MTP_REPLY, (_, args) => {
32 |       reportBugsWindow(false, false)?.send(
33 |         IpcEvents.REPORT_BUGS_DISPOSE_MTP_REPLY_FROM_MAIN,
34 |         args
35 |       );
36 |     });
37 |   };
38 | }
39 | 


--------------------------------------------------------------------------------
/app/services/ipc-events/IpcEventType.js:
--------------------------------------------------------------------------------
 1 | export class IpcEvents {
 2 |   static OPEN_FAQS_WINDOW = 'ipc.window.faqs';
 3 | 
 4 |   static OPEN_HELP_PHONE_NOT_CONNECTING_WINDOW =
 5 |     'ipc.window.helpPhoneNotConnecting';
 6 | 
 7 |   static OPEN_HELP_PRIVACY_POLICY_WINDOW = 'ipc.window.privacyPolicy';
 8 | 
 9 |   static OPEN_KEYBOARD_SHORTCUTS_WINDOW = 'ipc.window.keyboardShortcuts';
10 | 
11 |   static REPORT_BUGS_DISPOSE_MTP = 'ipc.reportBugsDisposeMtp';
12 | 
13 |   static REPORT_BUGS_DISPOSE_MTP_REPLY = 'ipc.reportBugsDisposeMtpReply';
14 | 
15 |   static REPORT_BUGS_DISPOSE_MTP_REPLY_FROM_MAIN =
16 |     'ipc.reportBugsDisposeMtpReply.fromMain';
17 | 
18 |   static USB_HOTPLUG = 'ipc.usbHotplug';
19 | }
20 | 


--------------------------------------------------------------------------------
/app/services/sentry/index.js:
--------------------------------------------------------------------------------
 1 | import * as Sentry from '@sentry/electron';
 2 | import { ENV_FLAVOR } from '../../constants/env';
 3 | import { SERVICE_KEYS } from '../../constants/serviceKeys';
 4 | import { getDeviceInfo } from '../../helpers/deviceInfo';
 5 | import { isEmpty } from '../../utils/funcs';
 6 | import { pkginfo } from '../../utils/pkginfo';
 7 | import { checkIf } from '../../utils/checkIf';
 8 | import { MTP_MODE } from '../../enums';
 9 | import { getMachineId } from '../../helpers/identifiers';
10 | 
11 | class SentryService {
12 |   constructor() {
13 |     if (!ENV_FLAVOR.reportToSenty) {
14 |       return;
15 |     }
16 | 
17 |     this.init();
18 |   }
19 | 
20 |   async init() {
21 |     Sentry.init({
22 |       dsn: SERVICE_KEYS.sentryDsn,
23 |       // disabled native crash reporting to respect user's privacy
24 |       enableNative: false,
25 |       release: pkginfo.version,
26 |     });
27 | 
28 |     this.machineId = getMachineId();
29 |   }
30 | 
31 |   async report({ error, title, mtpMode }) {
32 |     checkIf(mtpMode, 'inObjectValues', MTP_MODE);
33 | 
34 |     if (!ENV_FLAVOR.reportToSenty) {
35 |       return;
36 |     }
37 | 
38 |     const deviceInfo = getDeviceInfo();
39 | 
40 |     Sentry.configureScope((scope) => {
41 |       if (!isEmpty(deviceInfo)) {
42 |         Object.keys(deviceInfo).forEach((a) => {
43 |           const item = deviceInfo[a];
44 | 
45 |           scope.setExtra(a, item);
46 |         });
47 |       }
48 | 
49 |       if (!isEmpty(title)) {
50 |         scope.setExtra('error title', title);
51 |       }
52 | 
53 |       scope.setExtra('MTP Mode', mtpMode);
54 | 
55 |       // this is a hashed value (sha-256)
56 |       scope.setUser({ id: this.machineId });
57 | 
58 |       Sentry.captureException(error);
59 |     });
60 |   }
61 | }
62 | 
63 | export const sentryService = new SentryService();
64 | 


--------------------------------------------------------------------------------
/app/store/configureStore/dev.js:
--------------------------------------------------------------------------------
 1 | /* eslint global-require: off */
 2 | /* eslint-disable import/no-import-module-exports */
 3 | 
 4 | import { createStore, applyMiddleware, compose } from 'redux';
 5 | import thunk from 'redux-thunk';
 6 | import { createHashHistory } from 'history';
 7 | import { routerMiddleware } from 'react-router-redux';
 8 | import { createLogger } from 'redux-logger';
 9 | import rootReducer from '../reducers';
10 | 
11 | const history = createHashHistory();
12 | 
13 | const configureStore = (initialState) => {
14 |   // Redux Configuration
15 |   const middleware = [];
16 |   const enhancers = [];
17 | 
18 |   // Thunk Middleware
19 |   middleware.push(thunk);
20 | 
21 |   // Logging Middleware
22 |   const logger = createLogger({
23 |     level: 'info',
24 |     collapsed: true,
25 |   });
26 | 
27 |   // Skip redux logs in console during the tests
28 |   if (process.env.NODE_ENV !== 'test') {
29 |     middleware.push(logger);
30 |   }
31 | 
32 |   // Router Middleware
33 |   const router = routerMiddleware(history);
34 | 
35 |   middleware.push(router);
36 | 
37 |   // If Redux DevTools Extension is installed use it, otherwise use Redux compose
38 |   const composeEnhancers =
39 |     window && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
40 |       ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
41 |       : compose;
42 | 
43 |   // Apply Middleware & Compose Enhancers
44 |   enhancers.push(applyMiddleware(...middleware));
45 |   const enhancer = composeEnhancers(...enhancers);
46 | 
47 |   // Create Store
48 |   const store = createStore(rootReducer(), initialState, enhancer);
49 | 
50 |   store.asyncReducers = {};
51 |   store.injectReducer = (key, reducer) => {
52 |     store.asyncReducers[key] = reducer;
53 |     store.replaceReducer(rootReducer(store.asyncReducers));
54 | 
55 |     return store;
56 |   };
57 | 
58 |   if (module.hot) {
59 |     module.hot.accept('../reducers', () =>
60 |       store.replaceReducer(require('../reducers').default)
61 |     );
62 |   }
63 | 
64 |   return store;
65 | };
66 | 
67 | export default { configureStore, history };
68 | 


--------------------------------------------------------------------------------
/app/store/configureStore/index.js:
--------------------------------------------------------------------------------
 1 | import configureStoreDev from './dev';
 2 | import configureStoreProd from './prod';
 3 | import { IS_PROD } from '../../constants/env';
 4 | 
 5 | const selectedConfigureStore = IS_PROD ? configureStoreProd : configureStoreDev;
 6 | 
 7 | const { configureStore } = selectedConfigureStore;
 8 | 
 9 | export const { history } = selectedConfigureStore;
10 | 
11 | export const store = configureStore();
12 | 


--------------------------------------------------------------------------------
/app/store/configureStore/prod.js:
--------------------------------------------------------------------------------
 1 | import { createStore, applyMiddleware } from 'redux';
 2 | import thunk from 'redux-thunk';
 3 | import { createHashHistory } from 'history';
 4 | import { routerMiddleware } from 'react-router-redux';
 5 | import rootReducer from '../reducers';
 6 | 
 7 | const history = createHashHistory();
 8 | const router = routerMiddleware(history);
 9 | const enhancer = applyMiddleware(thunk, router);
10 | 
11 | const configureStore = (initialState) => {
12 |   const store = createStore(rootReducer(), initialState, enhancer);
13 | 
14 |   store.asyncReducers = {};
15 |   store.injectReducer = (key, reducer) => {
16 |     store.asyncReducers[key] = reducer;
17 |     store.replaceReducer(rootReducer(store.asyncReducers));
18 | 
19 |     return store;
20 |   };
21 | 
22 |   return store;
23 | };
24 | 
25 | export default { configureStore, history };
26 | 


--------------------------------------------------------------------------------
/app/store/reducers/index.js:
--------------------------------------------------------------------------------
 1 | import { combineReducers } from 'redux';
 2 | import { routerReducer as router } from 'react-router-redux';
 3 | import Alerts from '../../containers/Alerts/reducers';
 4 | import Settings from '../../containers/Settings/reducers';
 5 | 
 6 | const rootReducer = (asyncReducers) =>
 7 |   combineReducers({
 8 |     Alerts,
 9 |     Settings,
10 |     router,
11 |     ...asyncReducers,
12 |   });
13 | 
14 | export default rootReducer;
15 | 


--------------------------------------------------------------------------------
/app/store/reducers/withReducer.js:
--------------------------------------------------------------------------------
 1 | import React from 'react';
 2 | import { object } from 'prop-types';
 3 | 
 4 | /* eslint-disable */
 5 | const withReducer = (key, reducer) => (WrappedComponent) => {
 6 |   const Extended = (props, context) => {
 7 |     context.store.injectReducer(key, reducer);
 8 |     return <WrappedComponent {...props} />;
 9 |   };
10 | 
11 |   Extended.contextTypes = {
12 |     store: object,
13 |   };
14 | 
15 |   return Extended;
16 | };
17 | 
18 | /* eslint-enable */
19 | export { withReducer };
20 | 


--------------------------------------------------------------------------------
/app/styles/js/index.js:
--------------------------------------------------------------------------------
1 | export { default as variables } from './variables';
2 | export { default as mixins } from './mixins';
3 | 


--------------------------------------------------------------------------------
/app/styles/js/variables.js:
--------------------------------------------------------------------------------
 1 | // common styling variable object which can be imported by components
 2 | export default (_) => {
 3 |   return {
 4 |     sizes: {
 5 |       toolbarHeight: 64,
 6 |       sidebarAreaPaneWidth: 300,
 7 |       sidebarAreaPaddingTop: 40,
 8 |       regularFontSize: 14,
 9 |     },
10 |     //   styles: {
11 |     //     bgColor: APP_THEME_COLOR_VAR.bgColor,
12 |     //     primaryColor: {
13 |     //       main: APP_THEME_COLOR_VAR.primaryMainColor,
14 |     //     },
15 |     //     secondaryColor: {
16 |     //       main: APP_THEME_COLOR_VAR.secondaryMainColor,
17 |     //     },
18 |     //     background: {
19 |     //       paper: APP_THEME_COLOR_VAR.paperBgColor,
20 |     //     },
21 |     //     icons: {
22 |     //       navbarRegular: APP_THEME_COLOR_VAR.contrastPrimaryMainColor,
23 |     //       disabled: APP_THEME_COLOR_VAR.disabledBgColor,
24 |     //     },
25 |     //     nativeSystemColor: APP_THEME_COLOR_VAR.nativeSystemColor,
26 |     //     tableHeaderFooterBgColor: APP_THEME_COLOR_VAR.tableHeaderFooterBgColor,
27 |     //     fileExplorerThinLineDividerColor:
28 |     //       APP_THEME_COLOR_VAR.fileExplorerThinLineDividerColor,
29 |     //     lightText1Color: APP_THEME_COLOR_VAR.lightText1Color,
30 |     //   },
31 |   };
32 | };
33 | 


--------------------------------------------------------------------------------
/app/styles/scss/app.global.scss:
--------------------------------------------------------------------------------
1 | @import './themes/fonts';
2 | @import './base/base';
3 | @import './themes/reset';
4 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/_base.scss:
--------------------------------------------------------------------------------
1 | //Base
2 | @import 'variables';
3 | @import 'mixins';
4 | @import 'extends';
5 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/_extends.scss:
--------------------------------------------------------------------------------
 1 | %marginAuto {
 2 |   @include margin-auto();
 3 | }
 4 | 
 5 | %clearfix {
 6 |   @include clearfix();
 7 | }
 8 | 
 9 | %inlineBlock {
10 |   @include inline-block();
11 | }
12 | 
13 | %hideText {
14 |   @include hide-text();
15 | }
16 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/_variables.scss:
--------------------------------------------------------------------------------
 1 | // ----------------------------------------------------------------------
 2 | // Font Sizes
 3 | // ----------------------------------------------------------------------
 4 | $regularSize: 14;
 5 | 
 6 | // ----------------------------------------------------------------------
 7 | // Font Families
 8 | // ----------------------------------------------------------------------
 9 | $roboto: 'Roboto', sans-serif;
10 | 
11 | // ----------------------------------------------------------------------
12 | // styles
13 | // ----------------------------------------------------------------------
14 | 
15 | $appBgColor: var(--app-bg-color) !default;
16 | 
17 | $appSecondaryColor: var(--app-secondary-main-color) !default;
18 | 
19 | $nativeSystemColor: var(--app-native-system-color) !default;
20 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_align-items.scss:
--------------------------------------------------------------------------------
 1 | // ----------------------------------------------------------------------
 2 | 
 3 | // Flex Align Items
 4 | 
 5 | // ----------------------------------------------------------------------
 6 | 
 7 | @mixin align-items($value) {
 8 |   -webkit-box-align: $value;
 9 |   -moz-box-align: $value;
10 |   -ms-flex-align: $value;
11 |   -webkit-align-items: $value;
12 |   align-items: $value;
13 | }
14 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_animate-link.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Animated link that has a fade-in underline
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include animate-link($screenGreen, $gothamMedium, 14);
14 | 
15 | @mixin animate-link($color, $font, $fontSize) {
16 |   font-family: $font;
17 | 
18 |   @include single-transition(border, 0.2s, ease-in-out, 0);
19 | 
20 |   text-decoration: none;
21 |   color: $color;
22 |   border-bottom: 1px solid transparent;
23 | 
24 |   @include rem('font-size', $fontSize);
25 | 
26 |   &:focus,
27 |   &:hover {
28 |     border-color: $color;
29 |   }
30 | }
31 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_animations.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Animations
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include animation('slide-down 5s 3');
14 | 
15 | @mixin animation($str) {
16 |   -webkit-animation: #{$str};
17 |   -moz-animation: #{$str};
18 |   -ms-animation: #{$str};
19 |   -o-animation: #{$str};
20 |   animation: #{$str};
21 | }
22 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_backface-visibility.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Backface-visibility
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include backface-visibility("hidden");
14 | 
15 | @mixin backface-visibility($value) {
16 |   -webkit-backface-visibility: $value;
17 |   -moz-backface-visibility: $value;
18 |   backface-visibility: $value;
19 | }
20 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_background-cover.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Background cover
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include background-cover();
14 | 
15 | @mixin background-cover() {
16 |   -webkit-background-size: cover;
17 |   -moz-background-size: cover;
18 |   -o-background-size: cover;
19 |   background-size: cover;
20 | }
21 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_border.scss:
--------------------------------------------------------------------------------
 1 | @mixin border-radius($value) {
 2 |   -moz-border-radius: $value;
 3 |   -webkit-border-radius: $value;
 4 |   border-radius: $value;
 5 | }
 6 | 
 7 | @mixin border($value) {
 8 |   border: $value;
 9 | }
10 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_box-model.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Box Model
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | @mixin box-sizing($box-model) {
14 |   -webkit-box-sizing: $box-model;
15 |   -moz-box-sizing: $box-model;
16 |   box-sizing: $box-model;
17 | }
18 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_box-shadow.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Box Shadow
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include box-shadow(1px, 2px, 2px, 2px, #000);
14 | 
15 | @mixin box-shadow(
16 |   $hoff: false,
17 |   $voff: false,
18 |   $blur: false,
19 |   $spread: false,
20 |   $color: false
21 | ) {
22 |   -webkit-box-shadow: $hoff $voff $blur $spread $color;
23 |   -moz-box-shadow: $hoff $voff $blur $spread $color;
24 |   box-shadow: $hoff $voff $blur $spread $color;
25 | }
26 | 
27 | @mixin box-shadow-1($value) {
28 |   -webkit-box-shadow: $value;
29 |   -moz-box-shadow: $value;
30 |   box-shadow: $value;
31 | }
32 | 
33 | @mixin box-shadow-2($value1, $value2, $value3) {
34 |   -webkit-box-shadow: $value1, $value2, $value3;
35 |   -moz-box-shadow: $value1, $value2, $value3;
36 |   box-shadow: $value1, $value2, $value3;
37 | }
38 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_breakpoint.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Media Query Breakpoints
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example @include breakpoint(940) { width:80%; }
14 | 
15 | @mixin breakpoint($size) {
16 |   @media only screen and (max-width: $size + px) {
17 |     @content;
18 |   }
19 | }
20 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_clearfix.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Clearfix after element
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include clearfix();
14 | 
15 | @mixin clearfix() {
16 |   & {
17 |     *zoom: 1;
18 |   }
19 |   &::before,
20 |   &::after {
21 |     content: '';
22 |     display: table;
23 |   }
24 |   &::after {
25 |     clear: both;
26 |   }
27 | }
28 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_display.scss:
--------------------------------------------------------------------------------
 1 | @mixin display($value) {
 2 |   display: $value;
 3 | }
 4 | 
 5 | @mixin display-none($important) {
 6 |   @if $important {
 7 |     $important: !important;
 8 |   }
 9 | 
10 |   display: none $important;
11 | }
12 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_display_flex.scss:
--------------------------------------------------------------------------------
1 | @mixin display_flex() {
2 |   display: -webkit-box;
3 |   display: -moz-box;
4 |   display: -ms-flexbox;
5 |   display: -webkit-flex;
6 |   display: flex;
7 | }
8 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_hide-text.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Hide Text
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include hide-text();
14 | 
15 | @mixin hide-text() {
16 |   position: relative;
17 |   text-indent: -99999px;
18 |   display: inline-block;
19 | }
20 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_horz-vert-center.scss:
--------------------------------------------------------------------------------
 1 | // example: @include horz-vert-center();
 2 | 
 3 | @mixin horz-vert-center($alignItem: true) {
 4 |   display: flex;
 5 |   justify-content: center;
 6 |   flex-direction: column;
 7 |   @if $alignItem {
 8 |     align-items: center;
 9 |   }
10 | }
11 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_hover-focus.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // -----------------------------------------------------------------------
 8 | 
 9 | // Hover and Focus
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example @include hoverFocus('text-decoration', 'none');
14 | 
15 | @mixin hoverFocus($property, $value) {
16 |   &:hover,
17 |   &:focus {
18 |     #{$property}: $value;
19 |   }
20 | }
21 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_inline-block.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Display inline block cross browser
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include inline-block();
14 | 
15 | /* stylelint-disable declaration-block-no-duplicate-properties */
16 | 
17 | @mixin inline-block() {
18 |   display: -moz-inline-stack;
19 |   display: inline-block;
20 |   vertical-align: top;
21 |   zoom: 1;
22 |   *display: inline;
23 | }
24 | 
25 | /* stylelint-enable declaration-block-no-duplicate-properties */
26 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_inner-shadow.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Inner Shadow
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include inner-shadow(1px, 2px, 2px, #000);
14 | 
15 | @mixin inner-shadow($hoff: false, $voff: false, $blur: false, $color: false) {
16 |   -webkit-box-shadow: inset $hoff $voff $blur $color;
17 |   -moz-box-shadow: inset $hoff $voff $blur $color;
18 |   box-shadow: inset $hoff $voff $blur $color;
19 | }
20 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_keyframes.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Keyframes
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include keyframes(slide-down) {0%{ opacity:1; } 90%{ opacity:0; }}
14 | 
15 | @mixin keyframes($animation-name) {
16 |   @-webkit-keyframes #{$animation-name} {
17 |     @content;
18 |   }
19 |   @-moz-keyframes #{$animation-name} {
20 |     @content;
21 |   }
22 |   @-ms-keyframes #{$animation-name} {
23 |     @content;
24 |   }
25 |   @-o-keyframes #{$animation-name} {
26 |     @content;
27 |   }
28 |   @keyframes #{$animation-name} {
29 |     @content;
30 |   }
31 | }
32 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_linear-gradient-angle.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Linear Gradient angle
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include linear-gradient(-10, #cccccc, #333333);
14 | 
15 | @mixin linear-gradient($angle, $colorStart, $colorStop) {
16 |   background: #{$colorStart}; /* Old browsers */
17 |   background: -moz-linear-gradient(
18 |     $angle,
19 |     #{$colorStart} 0%,
20 |     #{$colorStop} 100%
21 |   ); /* FF3.6+ */
22 | 
23 |   background: -webkit-gradient(
24 |     linear,
25 |     left bottom,
26 |     right top,
27 |     color-stop(0%, #{$colorStart}),
28 |     color-stop(100%, #{$colorStop})
29 |   ); /* Chrome,Safari4+ */
30 | 
31 |   background: -webkit-linear-gradient(
32 |     45deg,
33 |     #{$colorStart} 0%,
34 |     #{$colorStop} 100%
35 |   ); /* Chrome10+,Safari5.1+ */
36 | 
37 |   background: -o-linear-gradient(
38 |     45deg,
39 |     #{$colorStart} 0%,
40 |     #{$colorStop} 100%
41 |   ); /* Opera 11.10+ */
42 | 
43 |   background: -ms-linear-gradient(
44 |     45deg,
45 |     #{$colorStart} 0%,
46 |     #{$colorStop} 100%
47 |   ); /* IE10+ */
48 | 
49 |   background: linear-gradient(
50 |     45deg,
51 |     #{$colorStart} 0%,
52 |     #{$colorStop} 100%
53 |   ); /* W3C */
54 | 
55 |   filter: progid:dximagetransform.microsoft.gradient( startColorstr='#{$colorStart}', endColorstr='#{$colorStop}',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
56 | }
57 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_linear-gradient.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // -----------------------------------------------------------------------
 8 | 
 9 | // Linear Gradients
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include linearGradient(#cccccc, #333333);
14 | 
15 | @mixin linearGradient($top, $bottom) {
16 |   background: #{$top}; /* Old browsers */
17 |   background: -moz-linear-gradient(
18 |     top,
19 |     #{$top} 0%,
20 |     #{$bottom} 100%
21 |   ); /* FF3.6+ */
22 | 
23 |   background: -webkit-gradient(
24 |     linear,
25 |     left top,
26 |     left bottom,
27 |     color-stop(0%, #{$top}),
28 |     color-stop(100%, #{$bottom})
29 |   ); /* Chrome,Safari4+ */
30 | 
31 |   background: -webkit-linear-gradient(
32 |     top,
33 |     #{$top} 0%,
34 |     #{$bottom} 100%
35 |   ); /* Chrome10+,Safari5.1+ */
36 | 
37 |   background: -o-linear-gradient(
38 |     top,
39 |     #{$top} 0%,
40 |     #{$bottom} 100%
41 |   ); /* Opera 11.10+ */
42 | 
43 |   background: -ms-linear-gradient(top, #{$top} 0%, #{$bottom} 100%); /* IE10+ */
44 |   background: linear-gradient(to bottom, #{$top} 0%, #{$bottom} 100%); /* W3C */
45 |   filter: progid:dximagetransform.microsoft.gradient( startColorstr='#{$top}', endColorstr='#{$bottom}', GradientType=0 ); /* IE6-9 */
46 | }
47 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_margin-auto.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Margin auto
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include margin-auto();
14 | 
15 | @mixin margin-auto() {
16 |   margin-left: auto;
17 |   margin-right: auto;
18 | }
19 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_mediumFont.scss:
--------------------------------------------------------------------------------
 1 | // ----------------------------------------------------------------------
 2 | 
 3 | // Medium Font
 4 | 
 5 | // ----------------------------------------------------------------------
 6 | 
 7 | // example @include medium-font();
 8 | 
 9 | @mixin medium-font() {
10 |   font-weight: bold;
11 |   letter-spacing: 0.4px;
12 | }
13 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_min-breakpoint.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Media Query Breakpoints
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example @include min-breakpoint(940) { width:80%; }
14 | 
15 | @mixin min-breakpoint($size) {
16 |   @media only screen and (min-width: $size + px) {
17 |     @content;
18 |   }
19 | }
20 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_opacity.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // -----------------------------------------------------------------------
 8 | 
 9 | // Opacity
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | @mixin opacity($opacity) {
14 |   opacity: $opacity;
15 |   $opacity-ie: $opacity * 100;
16 | 
17 |   filter: alpha(opacity=$opacity-ie); //IE8
18 | }
19 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_placeholder.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Change placeholder text color
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include placeholder-color(#333);
14 | 
15 | @mixin placeholder-color($color) {
16 |   &.placeholder {
17 |     color: $color;
18 |   }
19 | 
20 |   &:-moz-placeholder {
21 |     color: $color;
22 |   }
23 | 
24 |   &::-webkit-input-placeholder {
25 |     color: $color;
26 |   }
27 | 
28 |   &:-ms-input-placeholder {
29 |     color: $color;
30 |   }
31 | }
32 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_rem.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // REM Units with PX fallback
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include rem("margin", 10, 5, 10, 5);
14 | // example: @include rem("font-size", 14);
15 | 
16 | @mixin rem($property, $values...) {
17 |   $n: length($values);
18 |   $i: 1;
19 | 
20 |   $pxlist: ();
21 |   $remlist: ();
22 | 
23 |   @while $i <= $n {
24 |     $itemVal: (nth($values, $i));
25 |     @if $itemVal != 'auto' {
26 |       $pxlist: append($pxlist, $itemVal + px);
27 |       //$remlist: append($remlist, ($itemVal / 10) + rem); // Use this if you've set HTML font size value to 62.5%
28 |       $remlist: append($remlist, ($itemVal / 16) + rem);
29 |     } @else {
30 |       $pxlist: append($pxlist, auto);
31 |       $remlist: append($remlist, auto);
32 |     }
33 | 
34 |     $i: $i + 1;
35 |   }
36 | 
37 |   #{$property}: $pxlist;
38 |   #{$property}: $remlist;
39 | }
40 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_replace-text.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Replace text
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include replace-text();
14 | 
15 | /* stylelint-disable font-family-no-missing-generic-family-keyword */
16 | 
17 | @mixin replace-text() {
18 |   border: 0;
19 |   color: transparent;
20 |   font: 0/0 a;
21 |   text-shadow: none;
22 | }
23 | 
24 | /* stylelint-enable font-family-no-missing-generic-family-keyword */
25 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_retina.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // -----------------------------------------------------------------------
 8 | 
 9 | // Retina Images
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include retina("logo2x.png", 100, 50);
14 | 
15 | /* stylelint-disable media-feature-name-no-unknown */
16 | 
17 | @mixin retina($image, $width, $height) {
18 |   @media (min--moz-device-pixel-ratio: 1.3),
19 |     (-o-min-device-pixel-ratio: 2.6/2),
20 |     (-webkit-min-device-pixel-ratio: 1.3),
21 |     (min-device-pixel-ratio: 1.3),
22 |     (min-resolution: 1.3dppx) {
23 |     background-image: url('#{$image}');
24 |     background-size: $width + px $height + px;
25 |     //background-size: $width / 10 + rem $height / 10 + rem; // Use this if you've set HTML font size value to 62.5%
26 |     background-size: $width / 16 + rem $height / 16 + rem;
27 |   }
28 | }
29 | 
30 | /* stylelint-enable media-feature-name-no-unknown */
31 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_single-transform.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Single Transform
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include flat-button($greyBlue, white, 5px 15px);
14 | 
15 | @mixin single-transform($deg) {
16 |   -ms-transform: rotate($deg);
17 |   -webkit-transform: rotate($deg);
18 |   transform: rotate($deg);
19 | }
20 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_text-shadow.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Text Shadow
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include single-text-shadow(1px, 2px, 2px, #000);
14 | 
15 | @mixin single-text-shadow(
16 |   $hoff: false,
17 |   $voff: false,
18 |   $blur: false,
19 |   $color: false
20 | ) {
21 |   text-shadow: $hoff $voff $blur $color;
22 | }
23 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_transform.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Transform
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include transform("origin", 0, 0);
14 | 
15 | @mixin transform($type, $values...) {
16 |   $n: length($values);
17 |   $i: 1;
18 | 
19 |   $originVal: ();
20 | 
21 |   @while $i <= $n {
22 |     $itemVal: (nth($values, $i));
23 |     @if $type == 'rotate' or $type == 'rotateY' or $type == 'rotateX' {
24 |       $originVal: append($originVal, $itemVal + deg);
25 |     } @else {
26 |       $originVal: append($originVal, $itemVal + px);
27 |     }
28 | 
29 |     $i: $i + 1;
30 |   }
31 | 
32 |   -webkit-transform: #{$type }($originVal);
33 |   -moz-transform: #{$type }($originVal);
34 |   transform: #{$type }($originVal);
35 | }
36 | 
37 | @mixin transform-1($values) {
38 |   -webkit-transform: $values;
39 |   -ms-transform: $values;
40 |   transform: $values;
41 | }
42 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_transitions.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Transitions
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include single-transition(background, 1s, ease-in-out, 0);
14 | 
15 | @mixin single-transition($property, $duration, $timing-function, $delay) {
16 |   -webkit-transition: $property $duration $timing-function $delay;
17 |   -moz-transition: $property $duration $timing-function $delay;
18 |   -o-transition: $property $duration $timing-function $delay;
19 |   transition: $property $duration $timing-function $delay;
20 | }
21 | 
22 | // example: @include double-transition(background, 1s, ease-in-out, 0, opacity, .1s, ease-in-out, 0);
23 | 
24 | @mixin double-transition(
25 |   $property1,
26 |   $duration1,
27 |   $timing-function1,
28 |   $delay1,
29 |   $property2,
30 |   $duration2,
31 |   $timing-function2,
32 |   $delay2
33 | ) {
34 |   -webkit-transition: $property1 $duration1 $timing-function1 $delay1,
35 |     $property2 $duration2 $timing-function2 $delay2;
36 |   -moz-transition: $property1 $duration1 $timing-function1 $delay1,
37 |     $property2 $duration2 $timing-function2 $delay2;
38 |   -o-transition: $property1 $duration1 $timing-function1 $delay1,
39 |     $property2 $duration2 $timing-function2 $delay2;
40 |   transition: $property1 $duration1 $timing-function1 $delay1,
41 |     $property2 $duration2 $timing-function2 $delay2;
42 | }
43 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_translate.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Translate
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include translate(0);
14 | 
15 | @mixin translate($value) {
16 |   -webkit-transform: translateZ($value);
17 |   -moz-transform: translateZ($value);
18 |   -ms-transform: translateZ($value);
19 |   -o-transform: translateZ($value);
20 |   transform: translateZ($value);
21 | }
22 | 


--------------------------------------------------------------------------------
/app/styles/scss/base/mixins/_triangles.scss:
--------------------------------------------------------------------------------
 1 | //------ SASS Useful Mixins ---------------------------------------------
 2 | 
 3 | // by Ryan Burgess
 4 | // https://github.com/ryanburgess/SASS-Useful-Mixins
 5 | // MIT © Ryan Burgess
 6 | 
 7 | // ----------------------------------------------------------------------
 8 | 
 9 | // Arrows / Triangles
10 | 
11 | // ----------------------------------------------------------------------
12 | 
13 | // example: @include arrow("left", #cccccc, 10);
14 | 
15 | /* stylelint-disable declaration-block-no-duplicate-properties */
16 | 
17 | @mixin arrow($direction, $color, $size) {
18 |   $pxSize: $size + px;
19 |   $remSize: ($size / 10) + rem;
20 | 
21 |   width: 0;
22 |   height: 0;
23 | 
24 |   @if $direction == 'left' {
25 |     border-top: $pxSize solid transparent;
26 |     border-right: $pxSize solid $color;
27 |     border-bottom: $pxSize solid transparent;
28 |     border-top: $remSize solid transparent;
29 |     border-right: $remSize solid $color;
30 |     border-bottom: $remSize solid transparent;
31 |   } @else if $direction == 'right' {
32 |     border-top: $pxSize solid transparent;
33 |     border-bottom: $pxSize solid transparent;
34 |     border-left: $pxSize solid $color;
35 |     border-top: $remSize solid transparent;
36 |     border-bottom: $remSize solid transparent;
37 |     border-left: $remSize solid $color;
38 |   } @else if $direction == 'up' {
39 |     border-left: $pxSize solid transparent;
40 |     border-right: $pxSize solid transparent;
41 |     border-bottom: $pxSize solid $color;
42 |     border-left: $remSize solid transparent;
43 |     border-right: $remSize solid transparent;
44 |     border-bottom: $remSize solid $color;
45 |   } @else if $direction == 'down' {
46 |     border-left: $pxSize solid transparent;
47 |     border-right: $pxSize solid transparent;
48 |     border-top: $pxSize solid $color;
49 |     border-left: $remSize solid transparent;
50 |     border-right: $remSize solid transparent;
51 |     border-top: $remSize solid $color;
52 |   }
53 | }
54 | 
55 | /* stylelint-enable declaration-block-no-duplicate-properties */
56 | 


--------------------------------------------------------------------------------
/app/styles/scss/themes/fonts.scss:
--------------------------------------------------------------------------------
1 | @import '~roboto-fontface/css/roboto/roboto-fontface.css';
2 | 


--------------------------------------------------------------------------------
/app/styles/scss/themes/reset.scss:
--------------------------------------------------------------------------------
 1 | body {
 2 |   width: 100%;
 3 |   background-color: var(--app-bg-color) !important;
 4 |   @include rem('font-size', $regularSize);
 5 | 
 6 |   font-family: $roboto;
 7 |   overflow-x: hidden;
 8 |   overflow-y: hidden;
 9 | }
10 | 
11 | a {
12 |   cursor: pointer;
13 |   color: $appSecondaryColor;
14 | }
15 | 
16 | *::-webkit-scrollbar-track {
17 |   -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0);
18 |   border-radius: 0;
19 |   background-color: var(--app-bg-color);
20 | }
21 | 
22 | *::-webkit-scrollbar {
23 |   width: 8px;
24 |   height: 8px;
25 |   opacity: 1;
26 |   transition: background-color 0.3s;
27 | }
28 | 
29 | *::-webkit-scrollbar-thumb:hover {
30 |   background-color: #135ba1;
31 | }
32 | 
33 | *::-webkit-scrollbar-thumb {
34 |   border-radius: 0;
35 |   -webkit-box-shadow: inset 0 0 3px rgba(0, 0, 0, 0);
36 |   background-color: #1976d2;
37 | }
38 | 
39 | kbd {
40 |   display: inline-block;
41 |   margin: 0 0.1em;
42 |   padding: 0.1em 0.6em;
43 |   font-size: 14px;
44 |   font-weight: bold;
45 |   line-height: 1.4;
46 |   color: #242729;
47 |   text-shadow: 0 1px 0 #fff;
48 |   background-color: #e1e3e5;
49 |   border: 1px solid #adb3b9;
50 |   border-radius: 3px;
51 |   box-shadow: 0 1px 0 rgba(12, 13, 14, 0.2), 0 0 0 2px #fff inset;
52 |   white-space: nowrap;
53 | }
54 | 


--------------------------------------------------------------------------------
/app/templates/appFeaturesPage.js:
--------------------------------------------------------------------------------
1 | export const APP_FEATURES_PAGE_TITLE = `New Features and Updates`;
2 | 


--------------------------------------------------------------------------------
/app/templates/fileExplorer.js:
--------------------------------------------------------------------------------
1 | export const helpPhoneNotConnecting = `FAQs - My phone is not connecting!`;
2 | 
3 | export const buyMeACoffeeText = `Buy me a Coffee (UPI, PayPal, Credit/Debit Cards, Internet Banking)`;
4 | 
5 | export const supportUsingPayPal = `Support us via PayPal`;
6 | 


--------------------------------------------------------------------------------
/app/templates/generateErrorReport.js:
--------------------------------------------------------------------------------
 1 | import { APP_NAME, APP_VERSION, AUTHOR_EMAIL } from '../constants/meta';
 2 | 
 3 | const subject = `Error Logs for ${APP_NAME} | Version: ${APP_VERSION}`;
 4 | const body = subject;
 5 | 
 6 | export const mailTo = `mailto:${AUTHOR_EMAIL}?Subject=${subject}&Body=${body}.`;
 7 | 
 8 | export const mailToInstructions = (zippedLogFileBaseName) =>
 9 |   `%0D%0A %0D%0A Attach the generated error report file "${zippedLogFileBaseName}" (which is found in your Desktop folder) along with this email.`;
10 | 
11 | export const reportGenerateError = `Error report generation failed. Try again!`;
12 | 
13 | export const REPORT_BUGS_PAGE_TITLE = `Report Bugs`;
14 | 


--------------------------------------------------------------------------------
/app/templates/helpFaqsPage.js:
--------------------------------------------------------------------------------
1 | export const HELP_PHONE_IS_NOT_CONNECTING = `Help - My Phone is not connecting`;
2 | 
3 | export const FAQS_PAGE_TITLE = `Help - FAQs`;
4 | 


--------------------------------------------------------------------------------
/app/templates/keyboardShortcutsPage.js:
--------------------------------------------------------------------------------
1 | export const KEYBOARD_SHORTCUTS_PAGE_TITLE = `Keyboard Shortcuts`;
2 | 


--------------------------------------------------------------------------------
/app/templates/loadProfileError.js:
--------------------------------------------------------------------------------
 1 | import { APP_NAME, APP_VERSION, AUTHOR_EMAIL } from '../constants/meta';
 2 | 
 3 | export const loadProfileErrorHtml = `
 4 |         <html lang="en-gb">
 5 |           <body>
 6 |               <h3>Unable to load profile files. Please restart the app. </h3>
 7 |               <p>Write to the developer if the problem persists.</p>
 8 |               <a href="mailto:${AUTHOR_EMAIL}?Subject=Unable to load profile files&Body=${APP_NAME} - ${APP_VERSION}">${AUTHOR_EMAIL}</a>
 9 |           </body>
10 |         </html>
11 |       `;
12 | 


--------------------------------------------------------------------------------
/app/templates/menu.js:
--------------------------------------------------------------------------------
1 | import { APP_NAME, APP_WEBSITE } from '../constants/meta';
2 | 
3 | const inviteViaEmailSubject = `Android File Transfer for macOS - OpenMTP`;
4 | 
5 | const inviteViaEmailBody = `Tired of using expensive, outdated, bug heavy, Android File Transfer apps for macOS? %0D%0A Download "${APP_NAME}" - The Most Advanced Android File Transfer App for macOS from ${APP_WEBSITE} for free. %0D%0A It's Safe, Transparent, Open-Source and FREE for a lifetime!`;
6 | 
7 | export const inviteViaEmail = `mailto:?Subject=${inviteViaEmailSubject}&Body=${inviteViaEmailBody}`;
8 | 


--------------------------------------------------------------------------------
/app/templates/privacyPolicyPage.js:
--------------------------------------------------------------------------------
1 | export const PRIVACY_POLICY_PAGE_TITLE = `Privacy Policy`;
2 | 


--------------------------------------------------------------------------------
/app/templates/socialMediaShareBtns.js:
--------------------------------------------------------------------------------
 1 | import { APP_DESC, APP_NAME, APP_WEBSITE } from '../constants/meta';
 2 | 
 3 | const twitterShareText = `Tired of using expensive, outdated, bug heavy, Android File Transfer apps for macOS?
 4 | 
 5 | Get "${APP_DESC}" by @ganeshrvel.
 6 | It's Safe, Transparent, Open-Source and FREE for a lifetime!
 7 | 
 8 | `;
 9 | 
10 | export const twitterShareUrl = `http://twitter.com/share?text=${encodeURIComponent(
11 |   twitterShareText
12 | )}&hashtags=${APP_NAME},AndroidFileTransfer,macOS&url=${APP_WEBSITE}`;
13 | 
14 | export const fbShareUrl = `http://www.facebook.com/sharer/sharer.php?u=${APP_WEBSITE}`;
15 | 
16 | const redditShareText = `Tired of using expensive, outdated, bug heavy, Android File Transfer apps for macOS? Get "${APP_DESC}" by /u/ganeshrnet. It's Safe, Transparent, Open-Source and FREE for a lifetime!`;
17 | 
18 | export const redditShareUrl = `http://www.reddit.com/submit?url=${APP_WEBSITE}&title=${encodeURIComponent(
19 |   redditShareText
20 | )}`;
21 | 


--------------------------------------------------------------------------------
/app/utils/date.js:
--------------------------------------------------------------------------------
 1 | import dayjs from 'dayjs';
 2 | import advancedFormat from 'dayjs/plugin/advancedFormat';
 3 | 
 4 | dayjs.extend(advancedFormat);
 5 | 
 6 | export const yearMonthNow = ({ monthInletters = false }) => {
 7 |   let monthFormat = `MM`;
 8 | 
 9 |   if (monthInletters) {
10 |     monthFormat = `MMM`;
11 |   }
12 | 
13 |   return dayjs().format(`YYYY-${monthFormat}`);
14 | };
15 | 
16 | export const dateTimeUnixTimestampNow = ({ monthInletters = false }) => {
17 |   let monthFormat = `MM`;
18 | 
19 |   if (monthInletters) {
20 |     monthFormat = `MMM`;
21 |   }
22 | 
23 |   return dayjs().format(`YYYY-${monthFormat}-DD HH:mm:ss (x)`);
24 | };
25 | 
26 | export const dateNow = ({ monthInletters = false }) => {
27 |   let monthFormat = `MM`;
28 | 
29 |   if (monthInletters) {
30 |     monthFormat = `MMM`;
31 |   }
32 | 
33 |   return dayjs().format(`YYYY-${monthFormat}-DD`);
34 | };
35 | 
36 | export const unixTimestampNow = () => {
37 |   return dayjs().format(`x`);
38 | };
39 | 
40 | export const msToTime = (milliseconds) => {
41 |   const hours = milliseconds / (1000 * 60 * 60);
42 |   const absoluteHours = Math.floor(hours);
43 |   const h = absoluteHours > 9 ? absoluteHours : `0${absoluteHours}`;
44 | 
45 |   const minutes = (hours - absoluteHours) * 60;
46 |   const absoluteMinutes = Math.floor(minutes);
47 |   const m = absoluteMinutes > 9 ? absoluteMinutes : `0${absoluteMinutes}`;
48 | 
49 |   const seconds = (minutes - absoluteMinutes) * 60;
50 |   const absoluteSeconds = Math.floor(seconds);
51 |   const s = absoluteSeconds > 9 ? absoluteSeconds : `0${absoluteSeconds}`;
52 | 
53 |   return `${h}:${m}:${s}`;
54 | };
55 | 
56 | export const daysDiff = (startDate, endDate) => {
57 |   const start = dayjs(startDate, 'YYYY-MM-DD');
58 |   const end = dayjs(endDate, 'YYYY-MM-DD');
59 | 
60 |   return start.diff(end, 'day');
61 | };
62 | 
63 | export const appDateFormat = (dateTime) => {
64 |   return dayjs(dateTime).format('YYYY-MM-DD HH:mm:ss');
65 | };
66 | 


--------------------------------------------------------------------------------
/app/utils/errors.js:
--------------------------------------------------------------------------------
 1 | export function getError(error) {
 2 |   if (isConsoleError(error)) {
 3 |     return error.message;
 4 |   }
 5 | 
 6 |   return error;
 7 | }
 8 | 
 9 | export function isConsoleError(e) {
10 |   return e && e.stack;
11 | }
12 | 


--------------------------------------------------------------------------------
/app/utils/eventHandling.js:
--------------------------------------------------------------------------------
 1 | import EventEmitter from 'events';
 2 | import util from 'util';
 3 | 
 4 | export default function EmitAppEvents() {
 5 |   EventEmitter.call(this);
 6 | }
 7 | 
 8 | util.inherits(EmitAppEvents, EventEmitter);
 9 | 
10 | export const appEvents = new EmitAppEvents();
11 | 


--------------------------------------------------------------------------------
/app/utils/files.js:
--------------------------------------------------------------------------------
 1 | import { join, parse } from 'path';
 2 | import { homedir as homedirOs } from 'os';
 3 | import { APP_BUNDLE_ID } from '../constants/meta';
 4 | 
 5 | const homeDir = homedirOs();
 6 | 
 7 | export const getAppDataPath = () => {
 8 |   switch (process.platform) {
 9 |     case 'darwin':
10 |       return join(homeDir, 'Library', 'Application Support', APP_BUNDLE_ID);
11 | 
12 |     case 'win32':
13 |       return join(process.env.APPDATA, APP_BUNDLE_ID);
14 | 
15 |     case 'linux':
16 |       return join(homeDir, APP_BUNDLE_ID);
17 | 
18 |     default: {
19 |       process.exit(1);
20 |     }
21 |   }
22 | };
23 | 
24 | export const pathUp = (filePath) => {
25 |   return filePath.replace(/\/$/, '').replace(/\/[^/]+$/, '') || '/';
26 | };
27 | 
28 | export const sanitizePath = (filePath) => {
29 |   return filePath.replace(/\/\/+/g, '/');
30 | };
31 | 
32 | export const baseName = (filePath) => {
33 |   if (typeof filePath === 'undefined' || filePath === null) {
34 |     return null;
35 |   }
36 | 
37 |   const parsedPath = pathInfo(filePath);
38 | 
39 |   return parsedPath !== null ? parsedPath.base : null;
40 | };
41 | 
42 | export const getExtension = (fileName, isFolder) => {
43 |   if (isFolder) {
44 |     return null;
45 |   }
46 | 
47 |   const parsedPath = pathInfo(fileName);
48 | 
49 |   return parsedPath !== null ? parsedPath.ext : null;
50 | };
51 | 
52 | export const pathInfo = (filePath) => {
53 |   return parse(filePath);
54 | };
55 | 


--------------------------------------------------------------------------------
/app/utils/getPlatform.js:
--------------------------------------------------------------------------------
 1 | import { platform, release } from 'os';
 2 | import macosVersion from 'macos-version';
 3 | import { OS_ARCH_TYPE } from '../constants';
 4 | 
 5 | export const getPlatform = () => {
 6 |   switch (platform()) {
 7 |     case 'aix':
 8 |     case 'freebsd':
 9 |     case 'linux':
10 |     case 'openbsd':
11 |     case 'android':
12 |       return 'linux';
13 |     case 'darwin':
14 |     case 'sunos':
15 |       return 'mac';
16 |     case 'win32':
17 |       return 'win';
18 |     default:
19 |       return null;
20 |   }
21 | };
22 | 
23 | // these are currently supported system architectures for binaries
24 | export const getBinariesSupportedSystemArchitecture = () => {
25 |   if (process.arch === 'arm64') {
26 |     return OS_ARCH_TYPE.arm64;
27 |   }
28 | 
29 |   return OS_ARCH_TYPE.amd64;
30 | };
31 | 
32 | export const getOsVersion = () => {
33 |   if (macosVersion.isMacOS) {
34 |     return macosVersion();
35 |   }
36 | 
37 |   return release();
38 | };
39 | 


--------------------------------------------------------------------------------
/app/utils/gzip.js:
--------------------------------------------------------------------------------
 1 | import { createGzip } from 'zlib';
 2 | import { createReadStream, createWriteStream } from 'fs';
 3 | import { log } from './log';
 4 | 
 5 | export const compressFile = async (_input, _output) => {
 6 |   try {
 7 |     await new Promise((resolve, reject) => {
 8 |       const stream = createReadStream(_input);
 9 | 
10 |       stream
11 |         .pipe(createGzip())
12 |         .pipe(createWriteStream(_output))
13 |         .on('finish', () => resolve(true))
14 |         .on('error', (err) => {
15 |           reject(err);
16 |         });
17 |     });
18 | 
19 |     return true;
20 |   } catch (e) {
21 |     log.error(e, `gzip -> compressFile`);
22 |   }
23 | };
24 | 


--------------------------------------------------------------------------------
/app/utils/imgsrc.js:
--------------------------------------------------------------------------------
 1 | /* eslint global-require: off, prefer-template: off */
 2 | 
 3 | /**
 4 |  * handle image import into the program.
 5 |  * default path: ../public/images/
 6 |  * @param filePath
 7 |  * @param returnNoImageFound (optional)
 8 |  * @returns {*}
 9 |  */
10 | export const imgsrc = (filePath, returnNoImageFound = true) => {
11 |   try {
12 |     return require('../public/images/' + filePath).default;
13 |   } catch (e) {
14 |     if (!returnNoImageFound) {
15 |       return null;
16 |     }
17 | 
18 |     return require('../public/images/no-image.png').default;
19 |   }
20 | };
21 | 


--------------------------------------------------------------------------------
/app/utils/isGoogleAndroidFileTransferActive.js:
--------------------------------------------------------------------------------
 1 | import { isProcessRunning } from './process';
 2 | 
 3 | export const isGoogleAndroidFileTransferActive = async () => {
 4 |   const isAftRunning = await isProcessRunning('Android File transfer.app');
 5 |   const isAftAgentRunning = await isProcessRunning(
 6 |     'Android File Transfer Agent.app'
 7 |   );
 8 | 
 9 |   return isAftRunning && isAftAgentRunning;
10 | };
11 | 


--------------------------------------------------------------------------------
/app/utils/isOnline.js:
--------------------------------------------------------------------------------
 1 | import dns from 'dns';
 2 | import { log } from './log';
 3 | 
 4 | export const isConnected = () => {
 5 |   try {
 6 |     return new Promise((resolve) => {
 7 |       dns.lookup('github.com', (err) => {
 8 |         if (err && err.code === 'ENOTFOUND') {
 9 |           resolve(false);
10 | 
11 |           return null;
12 |         }
13 | 
14 |         resolve(true);
15 |       });
16 |     });
17 |   } catch (e) {
18 |     log.error(e, `isOnline -> isConnected`);
19 |   }
20 | };
21 | 


--------------------------------------------------------------------------------
/app/utils/isPackaged.js:
--------------------------------------------------------------------------------
1 | import { isPackaged as _isPackaged } from 'electron-is-packaged';
2 | 
3 | export const isPackaged = _isPackaged;
4 | 


--------------------------------------------------------------------------------
/app/utils/pkginfo.js:
--------------------------------------------------------------------------------
 1 | import { join } from 'path';
 2 | import { readFileSync } from 'fs';
 3 | import { rootPath } from 'electron-root-path';
 4 | 
 5 | let _pkginfo = {};
 6 | 
 7 | // eslint-disable-next-line no-undef
 8 | if (typeof PKG_INFO !== 'undefined' && PKG_INFO !== null) {
 9 |   // eslint-disable-next-line no-undef
10 |   _pkginfo = PKG_INFO;
11 | } else {
12 |   /* This is a fallback incase the webpack DefinePlugin modules hasn't been initialized yet. */
13 |   /* Developement mode only */
14 |   _pkginfo = JSON.parse(
15 |     readFileSync(join(rootPath, 'package.json'), { encoding: 'utf8' })
16 |   );
17 | }
18 | 
19 | export const pkginfo = _pkginfo;
20 | 


--------------------------------------------------------------------------------
/app/utils/process.js:
--------------------------------------------------------------------------------
 1 | import { spawn } from 'child_process';
 2 | import { checkIf } from './checkIf';
 3 | import { log } from './log';
 4 | 
 5 | // this is to prevent grep from appearing in the pslist and thus polluting the output
 6 | const queryToRegex = (str) => {
 7 |   if (typeof str === 'undefined' || str === null) {
 8 |     return '';
 9 |   }
10 | 
11 |   if (str.trim() === '') {
12 |     return '';
13 |   }
14 | 
15 |   str.replace(str.charAt(0), `[${str.charAt(0)}]`);
16 | };
17 | 
18 | export const isProcessRunning = (query) => {
19 |   checkIf(query, 'string');
20 | 
21 |   return new Promise((resolve) => {
22 |     let stdout = '';
23 |     let stderr;
24 | 
25 |     const child = spawn('ps', ['aux']);
26 |     const grep = spawn('grep', [`"${queryToRegex(query)}"`]);
27 | 
28 |     child.stdout.pipe(grep.stdin);
29 | 
30 |     child.stdout.on('data', (data) => {
31 |       stdout += data;
32 |     });
33 | 
34 |     child.stderr.on('data', (data) => {
35 |       stderr = data;
36 |     });
37 | 
38 |     child.on('exit', (code) => {
39 |       if (code > 1 && stderr) {
40 |         log.error(stderr, 'isProcessRunning -> exit');
41 | 
42 |         return resolve(false);
43 |       }
44 | 
45 |       return resolve(
46 |         (stdout ?? '')?.toLowerCase().indexOf(query?.toLowerCase()) > -1
47 |       );
48 |     });
49 |   }).catch((e) => {
50 |     log.error(e, 'isProcessRunning -> err');
51 | 
52 |     return Promise.resolve(false);
53 |   });
54 | };
55 | 


--------------------------------------------------------------------------------
/app/utils/styleResets.js:
--------------------------------------------------------------------------------
1 | export const resetOverFlowY = () => {
2 |   if (typeof document !== 'undefined' && document) {
3 |     document.body.style.overflowY = 'auto';
4 |   }
5 | };
6 | 


--------------------------------------------------------------------------------
/app/utils/styles.js:
--------------------------------------------------------------------------------
 1 | import { isString } from './funcs';
 2 | 
 3 | export const setStyle = (selector, styles) => {
 4 |   let elem;
 5 | 
 6 |   if (isString(selector)) {
 7 |     elem = document.querySelector(selector);
 8 |   } else {
 9 |     elem = selector;
10 |   }
11 | 
12 |   if (!elem) {
13 |     return;
14 |   }
15 | 
16 |   let styleString = '';
17 | 
18 |   Object.keys(styles).map((a) => {
19 |     const item = styles[a];
20 | 
21 |     styleString += `${a}:${item};`;
22 | 
23 |     return a;
24 |   });
25 | 
26 |   elem.setAttribute('style', styleString);
27 | };
28 | 


--------------------------------------------------------------------------------
/app/utils/url.js:
--------------------------------------------------------------------------------
 1 | import { shell } from 'electron';
 2 | 
 3 | export const openExternalUrl = (url, events = null) => {
 4 |   if (events) {
 5 |     events.preventDefault();
 6 |   }
 7 | 
 8 |   shell.openExternal(url);
 9 | };
10 | 


--------------------------------------------------------------------------------
/app/vendors/pretty-file-icons/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2017 Unknown
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 


--------------------------------------------------------------------------------
/app/vendors/pretty-file-icons/README.md:
--------------------------------------------------------------------------------
 1 | # Pretty File Icons
 2 | 
 3 | Pretty colorful icons for files (in svg format).
 4 | 
 5 | Icon pack author: [Madebyoliver](http://www.flaticon.com/authors/madebyoliver).
 6 | Icons are published as-is and under the licence by [flaticon.com](http://flaticon.com).
 7 | Licence for everything except icons is MIT.
 8 | 
 9 | See [index.json](index.json) for available icons list. Live preview is
10 | available [here](https://kravets-levko.github.io/pretty-file-icons/preview.html).
11 |  
12 | ## Usage
13 |  
14 | Just download image files and use them. Also, this package is available on NPM:
15 | ```
16 | npm install pretty-file-icons
17 | ```
18 |  
19 | In addition, this package contains mapping for some file extensions - see the
20 | [index.json](index.json) file. Also, it can be used in javascript applications 
21 | to retrieve icon names by file name:
22 | ```javascript
23 | var prettyFileIcons = require('pretty-file-icons');
24 | 
25 | console.log(prettyFileIcons.getIcon('test.csv'));
26 | console.log(prettyFileIcons.getIcon('test.csv', 'svg'));
27 | console.log(prettyFileIcons.getIcon('.test', 'svg'));
28 | 
29 | // Prints:
30 | // csv
31 | // csv.svg
32 | // unknown.svg
33 | ```
34 |   
35 | ## Preview:
36 |   
37 | ![Preview](preview.png)  
38 | 


--------------------------------------------------------------------------------
/app/vendors/pretty-file-icons/index.js:
--------------------------------------------------------------------------------
 1 | 'use strict';
 2 | 
 3 | var path = require('path');
 4 | 
 5 | var extensions = require('./index.json');
 6 | var unknown = extensions[''];
 7 | 
 8 | function isString(value) {
 9 |   return (typeof value === 'string') ||
10 |     (Object.prototype.toString.call(value) === '[object String]');
11 | }
12 | 
13 | function getIcon(filename, type) {
14 |   // Extract extension from the filename
15 |   var ext = isString(filename) ? path.extname(filename).toLowerCase() : '';
16 | 
17 |   // Validate type - it should be 'svg' or '.svg'
18 |   type = isString(type) ? type.toLowerCase() : '';
19 |   if (type.charAt(0) === '.') {
20 |     type = type.substr(1, type.length);
21 |   }
22 |   if (['svg'].indexOf(type) >= 0) {
23 |     type = '.' + type;
24 |   } else {
25 |     type = '';
26 |   }
27 | 
28 |   return (extensions[ext] || unknown) + type;
29 | }
30 | 
31 | module.exports.getIcon = getIcon;
32 | 
33 | module.exports.unknown = unknown;
34 | module.exports.extensions = extensions;
35 | 


--------------------------------------------------------------------------------
/app/vendors/pretty-file-icons/index.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "": "unknown",
 3 |   "audio": "audio",
 4 |   "video": "video",
 5 |   "text": "text",
 6 |   "archive": "archive",
 7 | 
 8 |   ".jpg": "jpg",
 9 |   ".jpe": "jpg",
10 |   ".jpeg": "jpg",
11 |   ".jfif": "jpg",
12 |   ".png": "png",
13 |   ".gif": "gif",
14 |   ".tiff": "tiff",
15 |   ".svg": "svg",
16 |   ".psd": "psd",
17 |   ".ai": "ai",
18 |   ".dwg": "dwg",
19 | 
20 |   ".iso": "iso",
21 |   ".mdf": "mdf",
22 |   ".nrg": "nrg",
23 | 
24 |   ".zip": "zip",
25 |   ".7z": "7z",
26 |   ".7zip": "7z",
27 |   ".arj": "arj",
28 |   ".rar": "rar",
29 |   ".gz": "archive",
30 |   ".gzip": "archive",
31 |   ".bz2": "archive",
32 |   ".bzip2": "archive",
33 |   ".tar": "archive",
34 | 
35 |   ".xls": "xls",
36 |   ".doc": "doc",
37 |   ".pdf": "pdf",
38 |   ".ppt": "ppt",
39 |   ".rtf": "rtf",
40 |   ".txt": "txt",
41 |   ".md": "text",
42 |   ".markdown": "text",
43 | 
44 |   ".avi": "avi",
45 |   ".mp2": "mp2",
46 |   ".mp3": "mp3",
47 |   ".mp4": "mp4",
48 |   ".fla": "fla",
49 |   ".mxf": "mxf",
50 |   ".wav": "wav",
51 |   ".wma": "wma",
52 |   ".aac": "aac",
53 |   ".flac": "flac",
54 | 
55 |   ".css": "css",
56 |   ".csv": "csv",
57 |   ".html": "html",
58 |   ".json": "json",
59 |   ".js": "js",
60 |   ".xml": "xml",
61 | 
62 |   ".dbf": "dbf",
63 |   ".exe": "exe",
64 |   ".fit": "fit"
65 | }
66 | 


--------------------------------------------------------------------------------
/app/vendors/pretty-file-icons/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "pretty-file-icons",
 3 |   "version": "2.2.1",
 4 |   "description": "Pretty colorful icons for files (in svg format).",
 5 |   "main": "index.js",
 6 |   "scripts": {
 7 |     "start": "xdg-open preview.html",
 8 |     "optimize": "svgo --config=./.svgo.yml --folder=./svg"
 9 |   },
10 |   "repository": {
11 |     "type": "git",
12 |     "url": "git+https://github.com/kravets-levko/pretty-file-icons.git"
13 |   },
14 |   "keywords": [
15 |     "file extensions",
16 |     "file types",
17 |     "file",
18 |     "types",
19 |     "extensions",
20 |     "file icons",
21 |     "icons",
22 |     "svg icons",
23 |     "vector icons",
24 |     "colorful icons"
25 |   ],
26 |   "author": "Unknown",
27 |   "license": "MIT",
28 |   "bugs": {
29 |     "url": "https://github.com/kravets-levko/pretty-file-icons/issues"
30 |   },
31 |   "contributors": [
32 |     {
33 |       "name": "Levko Kravets",
34 |       "email": "levko.ne@gmail.com"
35 |     }
36 |   ],
37 |   "devDependencies": {
38 |     "svgo": "^0.7.2"
39 |   }
40 | }
41 | 


--------------------------------------------------------------------------------
/blobs/binaries/.gitkeep:
--------------------------------------------------------------------------------
1 | 
2 | 


--------------------------------------------------------------------------------
/blobs/binaries/libusb_1.0.22_el_capitan_darwin_amd64.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/blobs/binaries/libusb_1.0.22_el_capitan_darwin_amd64.tar.gz


--------------------------------------------------------------------------------
/blobs/images/file-explorer-bluebg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/blobs/images/file-explorer-bluebg.jpg


--------------------------------------------------------------------------------
/blobs/images/file-explorer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/blobs/images/file-explorer.png


--------------------------------------------------------------------------------
/blobs/images/file-transfer-bluebg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/blobs/images/file-transfer-bluebg.jpg


--------------------------------------------------------------------------------
/blobs/images/file-transfer-large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/blobs/images/file-transfer-large.png


--------------------------------------------------------------------------------
/blobs/images/file-transfer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/blobs/images/file-transfer.png


--------------------------------------------------------------------------------
/build/entitlements.mac.plist:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 |   <dict>
 5 |     <key>com.apple.security.cs.allow-dyld-environment-variables</key>
 6 |     <true/>
 7 |     <key>com.apple.security.cs.disable-library-validation</key>
 8 |     <true/>
 9 |     <key>com.apple.security.cs.allow-jit</key>
10 |     <true/>
11 |     <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
12 |     <true/>
13 |     <key>com.apple.security.files.user-selected.read-only</key>
14 |     <true/>
15 |     <key>com.apple.security.files.user-selected.read-write</key>
16 |     <true/>
17 |     <key>com.apple.security.personal-information.photos-library</key>
18 |     <true/>
19 |     <key>com.apple.security.network.server</key>
20 |     <true/>
21 |     <key>com.apple.security.network.client</key>
22 |     <true/>
23 |   </dict>
24 | </plist>
25 | 


--------------------------------------------------------------------------------
/build/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icon.icns


--------------------------------------------------------------------------------
/build/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icon.ico


--------------------------------------------------------------------------------
/build/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icon.png


--------------------------------------------------------------------------------
/build/icons/1024x1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icons/1024x1024.png


--------------------------------------------------------------------------------
/build/icons/128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icons/128x128.png


--------------------------------------------------------------------------------
/build/icons/16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icons/16x16.png


--------------------------------------------------------------------------------
/build/icons/256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icons/256x256.png


--------------------------------------------------------------------------------
/build/icons/32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icons/32x32.png


--------------------------------------------------------------------------------
/build/icons/512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icons/512x512.png


--------------------------------------------------------------------------------
/build/icons/64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/icons/64x64.png


--------------------------------------------------------------------------------
/build/mac/bin/amd64/kalam.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/amd64/kalam.dylib


--------------------------------------------------------------------------------
/build/mac/bin/amd64/kalam_debug_report:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/amd64/kalam_debug_report


--------------------------------------------------------------------------------
/build/mac/bin/amd64/libusb.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/amd64/libusb.dylib


--------------------------------------------------------------------------------
/build/mac/bin/arm64/kalam.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/arm64/kalam.dylib


--------------------------------------------------------------------------------
/build/mac/bin/arm64/kalam_debug_report:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/arm64/kalam_debug_report


--------------------------------------------------------------------------------
/build/mac/bin/arm64/libusb.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/arm64/libusb.dylib


--------------------------------------------------------------------------------
/build/mac/bin/medieval/amd64/kalam.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/medieval/amd64/kalam.dylib


--------------------------------------------------------------------------------
/build/mac/bin/medieval/amd64/kalam_debug_report:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/medieval/amd64/kalam_debug_report


--------------------------------------------------------------------------------
/build/mac/bin/medieval/amd64/libusb.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/medieval/amd64/libusb.dylib


--------------------------------------------------------------------------------
/build/mac/bin/mtp-cli:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/build/mac/bin/mtp-cli


--------------------------------------------------------------------------------
/build/sample.entitlements.mas.plist:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 | <plist version="1.0">
 4 | 	<dict>
 5 | 		<key>com.apple.security.app-sandbox</key>
 6 | 		<true/>
 7 | 		<key>com.apple.security.application-groups</key>
 8 | 		<string><TEAM_ID>.<BUNDLE_ID></string>
 9 | 		<key>com.apple.security.network.client</key>
10 | 		<true/>
11 | 		<key>com.apple.security.device.usb</key>
12 | 		<true/>
13 | 		<key>com.apple.security.files.user-selected.read-write</key>
14 | 		<true/>
15 | 		<key>com.apple.security.files.user-selected.read-only</key>
16 | 		<true/>
17 | 		<key>com.apple.security.files.downloads.read-write</key>
18 | 		<true/>
19 | 		<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
20 |         <true/>
21 | 	</dict>
22 | </plist>
23 | 
24 | 


--------------------------------------------------------------------------------
/config/dev-app-update.yml:
--------------------------------------------------------------------------------
1 | owner: ganeshrvel
2 | repo: openmtp-testflight # use openmtp for testing the live release
3 | provider: github
4 | private: false
5 | 


--------------------------------------------------------------------------------
/config/env/env.dev.js:
--------------------------------------------------------------------------------
1 | module.exports.PORT = 4642;
2 | 


--------------------------------------------------------------------------------
/config/env/env.prod.js:
--------------------------------------------------------------------------------
1 | module.exports.PORT = 4642;
2 | 


--------------------------------------------------------------------------------
/config/env/index.js:
--------------------------------------------------------------------------------
1 | /* eslint prefer-destructuring: ["error", {AssignmentExpression: {array: true}}] */
2 | const IS_PROD = require('../../app/constants/env').IS_PROD;
3 | 
4 | const PORT_PROD = require('./env.prod').PORT;
5 | 
6 | const PORT_DEV = require('./env.dev').PORT;
7 | 
8 | module.exports.PORT = process.env.PORT || IS_PROD ? PORT_PROD : PORT_DEV;
9 | 


--------------------------------------------------------------------------------
/docs-sources/images/file-explorer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/docs-sources/images/file-explorer.png


--------------------------------------------------------------------------------
/docs-sources/images/file-transfer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/docs-sources/images/file-transfer.png


--------------------------------------------------------------------------------
/docs-sources/styles/base/_base.scss:
--------------------------------------------------------------------------------
1 | @import '../../../app/styles/scss/base/base';
2 | @import 'themes';
3 | 


--------------------------------------------------------------------------------
/docs-sources/styles/base/_themes.scss:
--------------------------------------------------------------------------------
1 | @import '~normalize.css/normalize.css';
2 | @import '~milligram/dist/milligram.min.css';
3 | 


--------------------------------------------------------------------------------
/docs-sources/utils/consts.js:
--------------------------------------------------------------------------------
1 | export const ALLOWED_GITHUB_FETCH_STATUSES = [200, 403, 404];
2 | 
3 | export const APP_GITHUB_URL = `https://github.com/ganeshrvel/openmtp`;
4 | 
5 | export const APP_GITHUB_API_URL = `https://api.github.com/repos/ganeshrvel/openmtp/releases/latest`;
6 | 


--------------------------------------------------------------------------------
/docs-sources/webpack/webpack.config.dev.js:
--------------------------------------------------------------------------------
 1 | const webpack = require('webpack');
 2 | 
 3 | const PORT = 4644;
 4 | 
 5 | module.exports = {
 6 |   devtool: 'inline-source-map',
 7 |   devServer: {
 8 |     port: PORT,
 9 |     compress: true,
10 |     hot: true,
11 |     // writeToDisk: true,
12 |   },
13 |   plugins: [
14 |     new webpack.HotModuleReplacementPlugin({
15 |       multiStep: false,
16 |     }),
17 |   ],
18 |   module: {
19 |     rules: [
20 |       {
21 |         test: /\.(scss|css|sass)$/,
22 |         use: [
23 |           {
24 |             loader: 'style-loader',
25 |           },
26 |           {
27 |             loader: 'css-loader',
28 |           },
29 |           {
30 |             loader: 'sass-loader',
31 |           },
32 |         ],
33 |       },
34 |     ],
35 |   },
36 | };
37 | 


--------------------------------------------------------------------------------
/docs-sources/webpack/webpack.config.prod.js:
--------------------------------------------------------------------------------
 1 | const path = require('path');
 2 | const MiniCssExtractPlugin = require('mini-css-extract-plugin');
 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin');
 4 | const TerserPlugin = require('terser-webpack-plugin');
 5 | const webpack = require('webpack');
 6 | const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
 7 | 
 8 | const buildPath = path.join(__dirname, '..', '..', 'docs');
 9 | 
10 | module.exports = {
11 |   plugins: [
12 |     new webpack.ProgressPlugin(),
13 |     new CleanWebpackPlugin({
14 |       dry: false,
15 |       verbose: true,
16 |       cleanOnceBeforeBuildPatterns: [`${buildPath}/bundle/*`],
17 |     }),
18 |     new MiniCssExtractPlugin({
19 |       filename: 'bundle/[name].[contenthash].css',
20 |     }),
21 |   ],
22 |   optimization: {
23 |     minimizer: [
24 |       new TerserPlugin({
25 |         parallel: true,
26 |         terserOptions: {
27 |           sourceMap: true,
28 |           mangle: true,
29 |           output: {
30 |             beautify: false,
31 |           },
32 |         },
33 |       }),
34 |       new OptimizeCSSAssetsPlugin({}),
35 |     ],
36 |   },
37 |   module: {
38 |     rules: [
39 |       {
40 |         test: /\.s?(a|c)ss$/,
41 |         use: [
42 |           MiniCssExtractPlugin.loader,
43 |           {
44 |             loader: 'css-loader',
45 |             options: {
46 |               modules: true,
47 |               sourceMap: true,
48 |               importLoaders: 1,
49 |             },
50 |           },
51 |           'sass-loader',
52 |         ],
53 |         include: /\.module\.s?(c|a)ss$/,
54 |       },
55 |       {
56 |         test: /\.s?(a|c)ss$/,
57 |         use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
58 |         exclude: /\.module\.s?(c|a)ss$/,
59 |       },
60 |     ],
61 |   },
62 | };
63 | 


--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | openmtp.ganeshrvel.com


--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate


--------------------------------------------------------------------------------
/docs/bundle/file-explorer.1b1a659da61529904113.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/docs/bundle/file-explorer.1b1a659da61529904113.png


--------------------------------------------------------------------------------
/docs/bundle/file-transfer.e01ae86967cd5e83a375.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/docs/bundle/file-transfer.e01ae86967cd5e83a375.png


--------------------------------------------------------------------------------
/docs/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ganeshrvel/openmtp/546d7f24fee324a990d69cc569891e9e4b80ea5e/docs/favicon.ico


--------------------------------------------------------------------------------
/docs/google25c4a4597b2b27f3.html:
--------------------------------------------------------------------------------
1 | google-site-verification: google25c4a4597b2b27f3.html


--------------------------------------------------------------------------------
/docs/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow:
3 | Disallow: /styles/
4 | Disallow: /images/
5 | Disallow: /bundle/
6 | 


--------------------------------------------------------------------------------
/docs/sitemap.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="UTF-8"?>
 2 | <urlset
 3 |       xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
 4 |       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5 |       xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9
 6 |             http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd">
 7 | 
 8 | 
 9 | <url>
10 |   <loc>https://ganeshrvel.github.io/openmtp/</loc>
11 |   <lastmod>2019-01-20T09:10:27+00:00</lastmod>
12 |   <priority>1.00</priority>
13 | </url>
14 | <url>
15 |   <loc>https://ganeshrvel.github.io/openmtp/privacy.html</loc>
16 |   <lastmod>2019-01-20T09:10:27+00:00</lastmod>
17 |   <priority>0.80</priority>
18 | </url>
19 | 
20 | 
21 | </urlset>


--------------------------------------------------------------------------------
/ffi/kalam/native/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | 


--------------------------------------------------------------------------------
/ffi/kalam/native/go.mod:
--------------------------------------------------------------------------------
 1 | module kalam
 2 | 
 3 | go 1.16
 4 | 
 5 | require (
 6 | 	github.com/ganeshrvel/go-mtpfs v1.0.4-0.20240426083057-1c3302b3c476
 7 | 	github.com/ganeshrvel/go-mtpx v0.0.0-20240426092756-18f12db021cc
 8 | 	github.com/json-iterator/go v1.1.12
 9 | 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
10 | )
11 | 
12 | ///##### Upgrade a package
13 | //go get github.com/<org-name>/<package-name>@<git-commit-hash>
14 | 
15 | //example: go get github.com/ganeshrvel/go-mtpfs@<git-commit-hash>
16 | //example: go get github.com/ganeshrvel/go-mtpx@<git-commit-hash>
17 | 
18 | ///##### Use a local package
19 | // replace github.com/ganeshrvel/go-mtpfs vxxxxxx-xxxxxxxxxx
20 | // with ../go-mtpfs
21 | 


--------------------------------------------------------------------------------
/ffi/kalam/native/kalam_debug_report/main.go:
--------------------------------------------------------------------------------
 1 | // +build !go1.17
 2 | 
 3 | package main
 4 | 
 5 | import (
 6 | 	"github.com/ganeshrvel/go-mtpx"
 7 | 	"log"
 8 | )
 9 | 
10 | func main() {
11 | 	log.Println("======================================================")
12 | 	log.Println("start kalam debug log")
13 | 	log.Printf("------------------------------------------------------\n")
14 | 
15 | 	dev, err := mtpx.Initialize(mtpx.Init{DebugMode: true})
16 | 	if err != nil {
17 | 		log.Printf("error initializing: %+v\n", err)
18 | 
19 | 		log.Printf("\n")
20 | 		log.Println("end kalam debug log")
21 | 		log.Println("======================================================")
22 | 
23 | 		return
24 | 	}
25 | 	log.Printf("\n------------------------------------------------------\n\n")
26 | 
27 | 	info, err := mtpx.FetchDeviceInfo(dev)
28 | 	if err != nil {
29 | 		log.Printf("error fetching device info: %+v\n", err)
30 | 	}
31 | 	log.Printf("\n------------------------------------------------------\n\n")
32 | 
33 | 	log.Printf("Storage: %+v\n", info)
34 | 	log.Printf("\n------------------------------------------------------\n\n")
35 | 
36 | 	storages, err := mtpx.FetchStorages(dev)
37 | 	if err != nil {
38 | 		log.Printf("error fetching storages info: %+v\n", err)
39 | 	}
40 | 	log.Printf("Storage: %+v\n", storages)
41 | 	log.Printf("\n------------------------------------------------------\n\n")
42 | 
43 | 	mtpx.Dispose(dev)
44 | 
45 | 	log.Printf("\n\n")
46 | 	log.Println("end kalam debug log")
47 | 	log.Println("======================================================")
48 | }
49 | 


--------------------------------------------------------------------------------
/ffi/kalam/native/send_to_js/constants.go:
--------------------------------------------------------------------------------
1 | package send_to_js
2 | 
3 | const DateTimeFormat = "2006-01-02T15:04:05.000Z"
4 | 


--------------------------------------------------------------------------------
/ffi/kalam/native/send_to_js/enums.go:
--------------------------------------------------------------------------------
 1 | package send_to_js
 2 | 
 3 | const (
 4 | 	ErrorMtpDetectFailed    ErrorType = "ErrorMtpDetectFailed"
 5 | 	ErrorMtpLockExists      ErrorType = "ErrorMtpLockExists"
 6 | 	ErrorDeviceChanged      ErrorType = "ErrorDeviceChanged"
 7 | 	ErrorDeviceSetup        ErrorType = "ErrorDeviceSetup"
 8 | 	ErrorMultipleDevice     ErrorType = "ErrorMultipleDevice"
 9 | 	ErrorAllowStorageAccess ErrorType = "ErrorAllowStorageAccess"
10 | 	ErrorDeviceLocked       ErrorType = "ErrorDeviceLocked"
11 | 	ErrorDeviceInfo         ErrorType = "ErrorDeviceInfo"
12 | 	ErrorStorageInfo        ErrorType = "ErrorStorageInfo"
13 | 	ErrorNoStorage          ErrorType = "ErrorNoStorage"
14 | 	ErrorStorageFull        ErrorType = "ErrorStorageFull"
15 | 	ErrorListDirectory      ErrorType = "ErrorListDirectory"
16 | 	ErrorFileNotFound       ErrorType = "ErrorFileNotFound"
17 | 	ErrorFilePermission     ErrorType = "ErrorFilePermission"
18 | 	ErrorLocalFileRead      ErrorType = "ErrorLocalFileRead"
19 | 	ErrorInvalidPath        ErrorType = "ErrorInvalidPath"
20 | 	ErrorFileTransfer       ErrorType = "ErrorFileTransfer"
21 | 	ErrorFileObjectRead     ErrorType = "ErrorFileObjectRead"
22 | 	ErrorSendObject         ErrorType = "ErrorSendObject"
23 | 	ErrorGeneral            ErrorType = "ErrorGeneral"
24 | )
25 | 


--------------------------------------------------------------------------------
/ffi/kalam/native/send_to_js/errors.go:
--------------------------------------------------------------------------------
 1 | package send_to_js
 2 | 
 3 | type MtpDetectFailedError struct {
 4 | 	error
 5 | }
 6 | 
 7 | type MtpChangedError struct {
 8 | 	error
 9 | }
10 | 


--------------------------------------------------------------------------------
/ffi/kalam/native/structs.go:
--------------------------------------------------------------------------------
 1 | package main
 2 | 
 3 | import (
 4 | 	"github.com/ganeshrvel/go-mtpfs/mtp"
 5 | 	"github.com/ganeshrvel/go-mtpx"
 6 | 	"os"
 7 | )
 8 | 
 9 | type verifyMtpSessionMode struct {
10 | 	skipDeviceChangeCheck bool
11 | }
12 | 
13 | type deviceContainer struct {
14 | 	dev        *mtp.Device
15 | 	deviceInfo *mtp.DeviceInfo
16 | 	locked     bool
17 | }
18 | 
19 | type MakeDirectoryInput struct {
20 | 	StorageId uint32 `json:"storageId"`
21 | 	FullPath  string `json:"fullPath"`
22 | }
23 | 
24 | type FileExistsInput struct {
25 | 	StorageId uint32   `json:"storageId"`
26 | 	Files     []string `json:"Files"`
27 | }
28 | 
29 | type DeleteFileInput struct {
30 | 	StorageId uint32   `json:"storageId"`
31 | 	Files     []string `json:"Files"`
32 | }
33 | 
34 | type RenameFileInput struct {
35 | 	StorageId   uint32 `json:"storageId"`
36 | 	FullPath    string `json:"fullPath"`
37 | 	NewFileName string `json:"newFileName"`
38 | }
39 | 
40 | type WalkInput struct {
41 | 	StorageId           uint32 `json:"storageId"`
42 | 	FullPath            string `json:"fullPath"`
43 | 	Recursive           bool   `json:"recursive"`
44 | 	SkipDisallowedFiles bool   `json:"skipDisallowedFiles"`
45 | 	SkipHiddenFiles     bool   `json:"skipHiddenFiles"`
46 | }
47 | 
48 | type UploadFilesInput struct {
49 | 	StorageId       uint32   `json:"storageId"`
50 | 	Sources         []string `json:"sources"`
51 | 	Destination     string   `json:"destination"`
52 | 	PreprocessFiles bool     `json:"preprocessFiles"`
53 | }
54 | 
55 | type DownloadFilesInput struct {
56 | 	StorageId       uint32   `json:"storageId"`
57 | 	Sources         []string `json:"sources"`
58 | 	Destination     string   `json:"destination"`
59 | 	PreprocessFiles bool     `json:"preprocessFiles"`
60 | }
61 | 
62 | type UploadPreprocessContainer struct {
63 | 	fi       *os.FileInfo
64 | 	fullPath string
65 | }
66 | 
67 | type DownloadPreprocessContainer struct {
68 | 	fi *mtpx.FileInfo
69 | }
70 | 
71 | type ProgressContainer struct {
72 | 	pInfo *mtpx.ProgressInfo
73 | }
74 | 


--------------------------------------------------------------------------------
/ffi/kalam/native/utils.go:
--------------------------------------------------------------------------------
 1 | package main
 2 | 
 3 | import (
 4 | 	"os"
 5 | )
 6 | 
 7 | func isDirLocal(name string) bool {
 8 | 	if fi, err := os.Stat(name); err == nil {
 9 | 		if fi.Mode().IsDir() {
10 | 			return true
11 | 		}
12 | 	}
13 | 	return false
14 | }
15 | 
16 | func existsLocal(filename string) bool {
17 | 	_, err := os.Stat(filename)
18 | 
19 | 	return !os.IsNotExist(err)
20 | }
21 | 


--------------------------------------------------------------------------------
/internals/scripts/AfterPack.js:
--------------------------------------------------------------------------------
 1 | const path = require('path');
 2 | const glob = require('glob');
 3 | const fs = require('fs-extra');
 4 | 
 5 | exports.default = async (context) => {
 6 |   // clean the unnecessary locales from packed app
 7 |   const lprojRegEx = /(en)\.lproj/g;
 8 |   const APP_NAME = context.packager.appInfo.productFilename;
 9 |   const APP_OUT_DIR = context.appOutDir;
10 |   const PLATFORM = context.packager.platform.name;
11 | 
12 |   const cwd = path.join(`${APP_OUT_DIR}`, `${APP_NAME}.app/Contents/Resources`);
13 |   const lproj = glob.sync('*.lproj', { cwd });
14 |   const _promises = [];
15 | 
16 |   switch (PLATFORM) {
17 |     case 'mac':
18 |       lproj.forEach((dir) => {
19 |         if (!lprojRegEx.test(dir)) {
20 |           _promises.push(fs.remove(path.join(cwd, dir)));
21 |         }
22 |       });
23 | 
24 |       break;
25 |     default:
26 |       break;
27 |   }
28 | 
29 |   return _promises;
30 | };
31 | 


--------------------------------------------------------------------------------
/internals/scripts/CheckBuildExist.js:
--------------------------------------------------------------------------------
 1 | // Check if the renderer and main bundles are built
 2 | import path from 'path';
 3 | import chalk from 'chalk';
 4 | import fs from 'fs';
 5 | 
 6 | function CheckBuildExist() {
 7 |   const mainPath = path.join(__dirname, '..', '..', 'app', 'main.prod.js');
 8 |   const rendererPath = path.join(
 9 |     __dirname,
10 |     '..',
11 |     '..',
12 |     'app',
13 |     'dist',
14 |     'renderer.prod.js'
15 |   );
16 | 
17 |   if (!fs.existsSync(mainPath)) {
18 |     throw new Error(
19 |       chalk.whiteBright.bgRed.bold(
20 |         'The main process is not built yet. Build it by running "yarn build-main"'
21 |       )
22 |     );
23 |   }
24 | 
25 |   if (!fs.existsSync(rendererPath)) {
26 |     throw new Error(
27 |       chalk.whiteBright.bgRed.bold(
28 |         'The renderer process is not built yet. Build it by running "yarn build-renderer"'
29 |       )
30 |     );
31 |   }
32 | }
33 | 
34 | CheckBuildExist();
35 | 


--------------------------------------------------------------------------------
/internals/scripts/CheckNodeEnv.js:
--------------------------------------------------------------------------------
 1 | import chalk from 'chalk';
 2 | 
 3 | export default function CheckNodeEnv(expectedEnv) {
 4 |   if (!expectedEnv) {
 5 |     throw new Error('"expectedEnv" not set');
 6 |   }
 7 | 
 8 |   if (process.env.NODE_ENV !== expectedEnv) {
 9 |     console.info(
10 |       chalk.whiteBright.bgRed.bold(
11 |         `"process.env.NODE_ENV" must be "${expectedEnv}" to use this webpack config`
12 |       )
13 |     );
14 |     process.exit(2);
15 |   }
16 | }
17 | 


--------------------------------------------------------------------------------
/internals/scripts/CheckPortInUse.js:
--------------------------------------------------------------------------------
 1 | import chalk from 'chalk';
 2 | import detectPort from 'detect-port';
 3 | import { PORT } from '../../config/env';
 4 | 
 5 | (function CheckPortInUse() {
 6 |   const _port = PORT.toString();
 7 | 
 8 |   detectPort(_port, (err, availablePort) => {
 9 |     if (_port !== String(availablePort)) {
10 |       throw new Error(
11 |         chalk.whiteBright.bgRed.bold(
12 |           // eslint-disable-next-line prefer-template
13 |           'Port "' +
14 |             _port +
15 |             '" on "localhost" is already in use. Please use another port.'
16 |         )
17 |       );
18 |     } else {
19 |       process.exit(0);
20 |     }
21 |   });
22 | })();
23 | 


--------------------------------------------------------------------------------
/internals/scripts/CheckYarn.js:
--------------------------------------------------------------------------------
 1 | const { execSync } = require('child_process');
 2 | const { semverSatisfies } = require('./semver');
 3 | 
 4 | const requiredVersionRange = '>=6.x <=8.16.0';
 5 | 
 6 | try {
 7 |   const npmVersion = execSync('npm -v').toString().trim();
 8 | 
 9 |   if (!semverSatisfies(npmVersion, requiredVersionRange)) {
10 |     console.error(
11 |       `Error: This project requires npm version ${requiredVersionRange}. You have version ${npmVersion}.\nPlease downgrade your npm, this is due to a bug in node-gyp. Github issue: https://github.com/ganeshrvel/openmtp/issues/367.\ncommand: npm install -g npm@8.16.0`
12 |     );
13 |     process.exit(1);
14 |   }
15 | 
16 |   console.info(`Using compatible npm version: ${npmVersion}`);
17 | } catch (error) {
18 |   console.error('Error checking npm version:', error);
19 | 
20 |   process.exit(1);
21 | }
22 | 
23 | if (!/yarn\.js$/.test(process.env.npm_execpath || '')) {
24 |   console.warn(
25 |     "\u001b[33mYou don't seem to be using yarn. This could produce unexpected results.\u001b[39m"
26 |   );
27 | }
28 | 


--------------------------------------------------------------------------------
/internals/scripts/Notarize.js:
--------------------------------------------------------------------------------
 1 | require('dotenv').config();
 2 | 
 3 | const path = require('path');
 4 | const fs = require('fs');
 5 | const { notarize: electronNotarize } = require('@electron/notarize');
 6 | const electronBuilderConfig = require('../../electron-builder-config');
 7 | 
 8 | const electronBuilderData = electronBuilderConfig();
 9 | 
10 | const { ELECTRON_NOTARIZE } = process.env;
11 | 
12 | exports.default = async (context) => {
13 |   const { electronPlatformName, appOutDir } = context;
14 | 
15 |   if (ELECTRON_NOTARIZE === 'NO') {
16 |     return;
17 |   }
18 | 
19 |   if (electronPlatformName !== 'darwin') {
20 |     return;
21 |   }
22 | 
23 |   const appBundleId = electronBuilderData.appId;
24 |   const appName = context.packager.appInfo.productFilename;
25 |   const appPath = path.join(appOutDir, `${appName}.app`);
26 |   const appleId = process.env.APPLEID;
27 |   const appleIdPassword = process.env.APPLE_APP_SPECIFIC_PASSWORD;
28 |   const appleTeamId = process.env.APPLE_TEAM_ID;
29 | 
30 |   if (!fs.existsSync(appPath)) {
31 |     throw new Error(`Cannot find application at: ${appPath}`);
32 |   }
33 | 
34 |   console.info(`Notarizing ${appBundleId} found at ${appPath}`);
35 | 
36 |   // eslint-disable-next-line no-return-await
37 |   return await electronNotarize({
38 |     appBundleId,
39 |     appPath,
40 |     appleId,
41 |     appleIdPassword,
42 |     teamId: appleTeamId,
43 |   });
44 | };
45 | 


--------------------------------------------------------------------------------
/internals/scripts/OptionalDepsInstall.js:
--------------------------------------------------------------------------------
 1 | const path = require('path');
 2 | const saveFile = require('fs').writeFileSync;
 3 | 
 4 | const pkgJsonPath = path.join(
 5 |   `${require.main.paths[0].split('node_modules')[0]}`,
 6 |   '../../',
 7 |   'package.json'
 8 | );
 9 | 
10 | const json = require(pkgJsonPath);
11 | 
12 | // json.dependencies['node-mac-permissions'] = '^2.2.1';
13 | 
14 | saveFile(pkgJsonPath, JSON.stringify(json, null, 2));
15 | 


--------------------------------------------------------------------------------
/internals/scripts/preinstall.sh:
--------------------------------------------------------------------------------
1 | #!/bin/zsh
2 | 
3 | node ./internals/scripts/CheckYarn.js
4 | 


--------------------------------------------------------------------------------
/internals/scripts/semver.js:
--------------------------------------------------------------------------------
 1 | exports.semverSatisfies = (version, range) => {
 2 |   const [gtOp, gtVersion] = gtSemver(range);
 3 |   const [ltOp, ltVersion] = ltSemver(range);
 4 |   const versionParts = version.split('.').map(Number);
 5 |   const gtVersionParts = gtVersion.split('.').map(Number);
 6 |   const ltVersionParts = ltVersion.split('.').map(Number);
 7 | 
 8 |   // eslint-disable-next-line no-plusplus
 9 |   for (let i = 0; i < 3; i++) {
10 |     const vp = versionParts[i] || 0;
11 |     const gtvp = gtVersionParts[i] || 0;
12 |     const ltvp = ltVersionParts[i] || 0;
13 | 
14 |     if (vp > ltvp || (vp === ltvp && ltOp === '<')) {
15 |       return false;
16 |     }
17 | 
18 |     if (vp < gtvp || (vp === gtvp && gtOp === '>')) {
19 |       return false;
20 |     }
21 |   }
22 | 
23 |   return true;
24 | };
25 | 
26 | const gtSemver = (range) => {
27 |   const gtPattern = />=?\s*(\d+(?:\.\d+(?:\.\d+)?)?)/.exec(range);
28 | 
29 |   return gtPattern ? ['>=', gtPattern[1]] : ['>=', '0.0.0'];
30 | };
31 | 
32 | const ltSemver = (range) => {
33 |   const ltPattern = /<=?\s*(\d+(?:\.\d+(?:\.\d+)?)?)/.exec(range);
34 | 
35 |   return ltPattern ? ['<=', ltPattern[1]] : ['<=', '9999.9999.9999'];
36 | };
37 | 


--------------------------------------------------------------------------------
/lint-staged.config.js:
--------------------------------------------------------------------------------
 1 | module.exports = {
 2 |   '*.{js,jsx,mjs}': ['yarn lint', 'yarn postlint-fix', 'git add'],
 3 |   '{*.json,.{babelrc,eslintrc,prettierrc,stylelintrc}}': [
 4 |     'prettier --ignore-path .eslintignore --parser json --write',
 5 |     'git add',
 6 |   ],
 7 |   '*.{css,scss}': ['yarn lint-styles', 'yarn postlint-styles-fix', 'git add'],
 8 |   '*.{html,md,yml}': [
 9 |     'prettier --ignore-path .eslintignore --single-quote --write',
10 |     'git add',
11 |   ],
12 |   '*.{js,jsx,mjs,ts,tsx,css,scss,html,md,yml}': ['git add'],
13 | };
14 | 


--------------------------------------------------------------------------------
/sample.env:
--------------------------------------------------------------------------------
1 | APPLEID="<value>"
2 | APPLE_APP_SPECIFIC_PASSWORD="<value>"
3 | APPLE_TEAM_ID="<value>"
4 | 


--------------------------------------------------------------------------------
/sample.sentry.properties:
--------------------------------------------------------------------------------
1 | defaults.url=https://sentry.io/
2 | defaults.org=<org>
3 | defaults.project=<project>
4 | auth.token=<token>
5 | 


--------------------------------------------------------------------------------
/scripts/cicd/axios.mjs:
--------------------------------------------------------------------------------
 1 | import process from 'process';
 2 | import axiosPackage from 'axios';
 3 | 
 4 | import { CODEMAGIC_BASE_URL } from './constants.mjs';
 5 | 
 6 | export const axios = axiosPackage.create({
 7 |   baseURL: CODEMAGIC_BASE_URL,
 8 | });
 9 | 
10 | axios.defaults.headers.common['Content-Type'] = 'application/json';
11 | axios.defaults.headers.common['x-auth-token'] =
12 |   process.env.CODEMAGIC_AUTH_TOKEN_ID;
13 | axios.defaults.timeout = 15000;
14 | 


--------------------------------------------------------------------------------
/scripts/cicd/base.mjs:
--------------------------------------------------------------------------------
 1 | import 'zx/globals';
 2 | 
 3 | require('dotenv').config();
 4 | 
 5 | process.env.FORCE_COLOR = 3;
 6 | $.shell = '/bin/zsh';
 7 | 
 8 | await 



    
    

    
    

    
    
    
    

    
    
    
    




    

    
The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
export LANG=en_US.UTF-8`; 9 | await
The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
export LC_ALL=en_US.UTF-8`; 10 | -------------------------------------------------------------------------------- /scripts/cicd/codemagic-start-mac-intel-x64-vm.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zx 2 | 3 | import 'zx/globals'; 4 | import process from 'process'; 5 | import './base.mjs'; 6 | import { IS_PROD_WORKFLOW } from './constants.mjs'; 7 | import { axios } from './axios.mjs'; 8 | 9 | let workflowId; 10 | if (IS_PROD_WORKFLOW) { 11 | workflowId = process.env.CODEMAGIC_INTEL_X64_WORKFLOW_ID_PROD; 12 | } else { 13 | workflowId = process.env.CODEMAGIC_INTEL_X64_WORKFLOW_ID_DEV; 14 | } 15 | 16 | // starting a new codemagic `macos-intel-x64-build` instance 17 | console.info(`starting a new CodeMagic 'macos-intel-x64-build' instance...\n`); 18 | try { 19 | await axios.post('/builds', { 20 | appId: `${process.env.CODEMAGIC_PUBLISH_PROJECT_ID}`, 21 | workflowId, 22 | branch: `${process.env.CM_BRANCH}`, 23 | environment: { 24 | variables: { 25 | CM_ARTIFACT_LINKS_M1_ARM64: process.env.CM_ARTIFACT_LINKS, 26 | }, 27 | }, 28 | }); 29 | } catch (e) { 30 | throw new Error( 31 | `starting a new CodeMagic 'macos-intel-x64-build' instance failed: ${e}` 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /scripts/cicd/constants.mjs: -------------------------------------------------------------------------------- 1 | import process from 'process'; 2 | import './base.mjs'; 3 | 4 | export const { WORKFLOW_ENV } = process.env; 5 | 6 | export const WORKFLOW_ENV_DEV = 'dev'; 7 | export const WORKFLOW_ENV_PROD = 'prod'; 8 | 9 | export const IS_DEV_WORKFLOW = WORKFLOW_ENV === WORKFLOW_ENV_DEV; 10 | export const IS_PROD_WORKFLOW = WORKFLOW_ENV === WORKFLOW_ENV_PROD; 11 | 12 | export const CODEMAGIC_BASE_URL = `https://api.codemagic.io`; 13 | -------------------------------------------------------------------------------- /webpack/config.base.js: -------------------------------------------------------------------------------- 1 | /* eslint global-require: off */ 2 | 3 | /** 4 | * Base webpack config used across other specific configs 5 | */ 6 | 7 | import { join } from 'path'; 8 | import webpack from 'webpack'; 9 | import { rootPath } from 'electron-root-path'; 10 | import { PATHS } from '../app/constants/paths'; 11 | 12 | const pkg = require(join(rootPath, 'package.json')); 13 | 14 | export default { 15 | externals: [...Object.keys(pkg.dependencies || {})], 16 | 17 | module: { 18 | rules: [ 19 | { 20 | test: /\.(js|jsx)?$/, 21 | exclude: /node_modules/, 22 | use: { 23 | loader: 'babel-loader', 24 | options: { 25 | cacheDirectory: true, 26 | }, 27 | }, 28 | }, 29 | ], 30 | }, 31 | 32 | output: { 33 | path: PATHS.app, 34 | // https://github.com/webpack/webpack/issues/1114 35 | libraryTarget: 'commonjs2', 36 | }, 37 | 38 | /** 39 | * Determine the array of extensions that should be used to resolve modules. 40 | */ 41 | resolve: { 42 | extensions: ['.js', '.jsx', '.json'], 43 | modules: [PATHS.nodeModules], 44 | }, 45 | 46 | plugins: [ 47 | // new webpack.IgnorePlugin({ resourceRegExp: /^(node-mac-permissions)$/u }), 48 | 49 | new webpack.EnvironmentPlugin({ 50 | NODE_ENV: 'production', 51 | }), 52 | 53 | new webpack.DefinePlugin({ 54 | PKG_INFO: { 55 | productName: JSON.stringify(pkg.productName), 56 | description: JSON.stringify(pkg.description), 57 | name: JSON.stringify(pkg.name), 58 | author: JSON.stringify(pkg.author), 59 | version: JSON.stringify(pkg.version), 60 | repository: JSON.stringify(pkg.repository), 61 | homepage: JSON.stringify(pkg.homepage), 62 | bugs: JSON.stringify(pkg.bugs), 63 | }, 64 | }), 65 | ], 66 | }; 67 | -------------------------------------------------------------------------------- /webpack/config.eslint.js: -------------------------------------------------------------------------------- 1 | /* eslint import/no-unresolved: off, import/no-self-import: off */ 2 | require('@babel/register'); 3 | 4 | module.exports = require('./config.renderer.dev.babel').default; 5 | -------------------------------------------------------------------------------- /webpack/config.renderer.dev.dll.babel.js: -------------------------------------------------------------------------------- 1 | /* eslint global-require: off, */ 2 | 3 | /** 4 | * Builds the DLL for development electron renderer process 5 | */ 6 | 7 | import webpack from 'webpack'; 8 | import path from 'path'; 9 | import merge from 'webpack-merge'; 10 | import baseConfig from './config.base'; 11 | import { PATHS } from '../app/constants/paths'; 12 | import CheckNodeEnv from '../internals/scripts/CheckNodeEnv'; 13 | 14 | const pkg = require('../package.json'); 15 | 16 | const dll = path.join(PATHS.root, 'dll'); 17 | 18 | CheckNodeEnv('development'); 19 | 20 | export default merge(baseConfig, { 21 | context: PATHS.root, 22 | devtool: 'eval', 23 | mode: 'development', 24 | target: 'electron-renderer', 25 | externals: ['fsevents', 'crypto-browserify'], 26 | 27 | /** 28 | * Use `module` from `config.renderer.dev.babel.js` 29 | */ 30 | module: require('./config.renderer.dev.babel').default.module, 31 | 32 | entry: { 33 | renderer: Object.keys(pkg.dependencies || {}), 34 | }, 35 | 36 | output: { 37 | library: 'renderer', 38 | path: dll, 39 | filename: '[name].dev.dll.js', 40 | libraryTarget: 'var', 41 | }, 42 | 43 | plugins: [ 44 | new webpack.DllPlugin({ 45 | path: path.join(dll, '[name].json'), 46 | name: '[name]', 47 | }), 48 | 49 | /** 50 | * Create global constants which can be configured at compile time. 51 | * 52 | * Useful for allowing different behaviour between development builds and 53 | * release builds 54 | * 55 | * NODE_ENV should be production so that modules do not perform certain 56 | * development checks 57 | */ 58 | new webpack.EnvironmentPlugin({ 59 | NODE_ENV: 'development', 60 | }), 61 | 62 | new webpack.LoaderOptionsPlugin({ 63 | debug: true, 64 | options: { 65 | context: PATHS.app, 66 | output: { 67 | path: dll, 68 | }, 69 | }, 70 | }), 71 | ], 72 | }); 73 | --------------------------------------------------------------------------------