├── .editorconfig
├── .erb
├── configs
│ ├── webpack.config.base.ts
│ ├── webpack.config.eslint.ts
│ ├── webpack.config.main.prod.ts
│ ├── webpack.config.renderer.dev.dll.ts
│ ├── webpack.config.renderer.dev.ts
│ ├── webpack.config.renderer.prod.ts
│ └── webpack.paths.ts
├── img
│ ├── erb-banner.svg
│ └── erb-logo.png
├── mocks
│ └── fileMock.js
└── scripts
│ ├── .eslintrc
│ ├── check-build-exists.ts
│ ├── check-native-dep.js
│ ├── check-node-env.js
│ ├── check-port-in-use.js
│ ├── clean.js
│ ├── delete-source-maps.js
│ ├── electron-rebuild.js
│ ├── link-modules.ts
│ └── notarize.js
├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── 1-Bug_report.md
│ ├── 2-Question.md
│ └── 3-Feature_request.md
├── config.yml
├── stale.yml
└── workflows
│ ├── publish.yml
│ └── quality-check.yml
├── .gitignore
├── .husky
└── pre-commit
├── LICENSE
├── README.md
├── assets
├── art.txt
├── assets.d.ts
├── entitlements.mac.plist
├── icon.icns
├── icon.ico
├── icon.png
└── icons
│ ├── 1024x1024.png
│ ├── 16x16.png
│ ├── 180x180.png
│ ├── 192x192.png
│ ├── 32x32.png
│ ├── 512x512.png
│ └── logo.png
├── install.sh
├── package.json
├── release
└── app
│ └── package.json
├── src
├── __tests__
│ └── App.test.tsx
├── main
│ ├── api
│ │ └── ipcHandler.ts
│ ├── constants
│ │ └── index.ts
│ ├── main.ts
│ ├── menu.ts
│ ├── preload.js
│ ├── types
│ │ └── index.ts
│ └── utils
│ │ ├── appUpdater.ts
│ │ ├── batchInstall.ts
│ │ ├── downloadFile.ts
│ │ ├── executeCmd.ts
│ │ ├── index.ts
│ │ ├── installExtensions.ts
│ │ └── resolveHtmlPath.ts
└── renderer
│ ├── App.css
│ ├── App.tsx
│ ├── api
│ └── index.ts
│ ├── components
│ ├── AccordionDropwdown.tsx
│ ├── ApkActions.tsx
│ ├── ConnectionActions.tsx
│ ├── FixedWidthBtn.tsx
│ ├── RevancedActions.tsx
│ ├── SystemActions.tsx
│ ├── TvActions.tsx
│ └── UpdateBtn.tsx
│ ├── constants
│ └── debloatCommands.ts
│ ├── context
│ ├── TerminalContext.tsx
│ ├── TerminalProvider.tsx
│ └── useTerminalContext.tsx
│ ├── index.ejs
│ ├── index.tsx
│ ├── theme.ts
│ └── types
│ └── index.ts
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 4
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.json]
12 | indent_size = 2
13 |
14 | [*.yml]
15 | indent_size = 2
16 |
17 | [*.md]
18 | trim_trailing_whitespace = false
19 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.base.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Base webpack config used across other specific configs
3 | */
4 |
5 | import webpack from 'webpack';
6 | import webpackPaths from './webpack.paths';
7 | import { dependencies as externals } from '../../release/app/package.json';
8 |
9 | export default {
10 | externals: [...Object.keys(externals || {})],
11 |
12 | stats: 'errors-only',
13 |
14 | module: {
15 | rules: [
16 | {
17 | test: /\.[jt]sx?$/,
18 | exclude: /node_modules/,
19 | use: {
20 | loader: 'ts-loader',
21 | options: {
22 | // Remove this line to enable type checking in webpack builds
23 | transpileOnly: true,
24 | },
25 | },
26 | },
27 | ],
28 | },
29 |
30 | output: {
31 | path: webpackPaths.srcPath,
32 | // https://github.com/webpack/webpack/issues/1114
33 | library: {
34 | type: 'commonjs2',
35 | },
36 | },
37 |
38 | /**
39 | * Determine the array of extensions that should be used to resolve modules.
40 | */
41 | resolve: {
42 | extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
43 | modules: [webpackPaths.srcPath, 'node_modules'],
44 | },
45 |
46 | plugins: [
47 | new webpack.EnvironmentPlugin({
48 | NODE_ENV: 'production',
49 | }),
50 | ],
51 | };
52 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.eslint.ts:
--------------------------------------------------------------------------------
1 | /* eslint import/no-unresolved: off, import/no-self-import: off */
2 |
3 | module.exports = require('./webpack.config.renderer.dev').default;
4 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.main.prod.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Webpack config for production electron main process
3 | */
4 |
5 | import path from 'path';
6 | import webpack from 'webpack';
7 | import { merge } from 'webpack-merge';
8 | import TerserPlugin from 'terser-webpack-plugin';
9 | import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
10 | import baseConfig from './webpack.config.base';
11 | import webpackPaths from './webpack.paths';
12 | import checkNodeEnv from '../scripts/check-node-env';
13 | import deleteSourceMaps from '../scripts/delete-source-maps';
14 |
15 | checkNodeEnv('production');
16 | deleteSourceMaps();
17 |
18 | const devtoolsConfig =
19 | process.env.DEBUG_PROD === 'true'
20 | ? {
21 | devtool: 'source-map',
22 | }
23 | : {};
24 |
25 | export default merge(baseConfig, {
26 | ...devtoolsConfig,
27 |
28 | mode: 'production',
29 |
30 | target: 'electron-main',
31 |
32 | entry: {
33 | main: path.join(webpackPaths.srcMainPath, 'main.ts'),
34 | preload: path.join(webpackPaths.srcMainPath, 'preload.js'),
35 | },
36 |
37 | output: {
38 | path: webpackPaths.distMainPath,
39 | filename: '[name].js',
40 | },
41 |
42 | optimization: {
43 | minimizer: [
44 | new TerserPlugin({
45 | parallel: true,
46 | }),
47 | ],
48 | },
49 |
50 | plugins: [
51 | new BundleAnalyzerPlugin({
52 | analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled',
53 | }),
54 |
55 | /**
56 | * Create global constants which can be configured at compile time.
57 | *
58 | * Useful for allowing different behaviour between development builds and
59 | * release builds
60 | *
61 | * NODE_ENV should be production so that modules do not perform certain
62 | * development checks
63 | */
64 | new webpack.EnvironmentPlugin({
65 | NODE_ENV: 'production',
66 | DEBUG_PROD: false,
67 | START_MINIMIZED: false,
68 | }),
69 | ],
70 |
71 | /**
72 | * Disables webpack processing of __dirname and __filename.
73 | * If you run the bundle in node.js it falls back to these values of node.js.
74 | * https://github.com/webpack/webpack/issues/2010
75 | */
76 | node: {
77 | __dirname: false,
78 | __filename: false,
79 | },
80 | });
81 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.renderer.dev.dll.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Builds the DLL for development electron renderer process
3 | */
4 |
5 | import webpack from 'webpack';
6 | import path from 'path';
7 | import { merge } from 'webpack-merge';
8 | import baseConfig from './webpack.config.base';
9 | import webpackPaths from './webpack.paths';
10 | import { dependencies } from '../../package.json';
11 | import checkNodeEnv from '../scripts/check-node-env';
12 |
13 | checkNodeEnv('development');
14 |
15 | const dist = webpackPaths.dllPath;
16 |
17 | export default merge(baseConfig, {
18 | context: webpackPaths.rootPath,
19 |
20 | devtool: 'eval',
21 |
22 | mode: 'development',
23 |
24 | target: 'electron-renderer',
25 |
26 | externals: ['fsevents', 'crypto-browserify'],
27 |
28 | /**
29 | * Use `module` from `webpack.config.renderer.dev.js`
30 | */
31 | module: require('./webpack.config.renderer.dev').default.module,
32 |
33 | entry: {
34 | renderer: Object.keys(dependencies || {}),
35 | },
36 |
37 | output: {
38 | path: dist,
39 | filename: '[name].dev.dll.js',
40 | library: {
41 | name: 'renderer',
42 | type: 'var',
43 | },
44 | },
45 |
46 | plugins: [
47 | new webpack.DllPlugin({
48 | path: path.join(dist, '[name].json'),
49 | name: '[name]',
50 | }),
51 |
52 | /**
53 | * Create global constants which can be configured at compile time.
54 | *
55 | * Useful for allowing different behaviour between development builds and
56 | * release builds
57 | *
58 | * NODE_ENV should be production so that modules do not perform certain
59 | * development checks
60 | */
61 | new webpack.EnvironmentPlugin({
62 | NODE_ENV: 'development',
63 | }),
64 |
65 | new webpack.LoaderOptionsPlugin({
66 | debug: true,
67 | options: {
68 | context: webpackPaths.srcPath,
69 | output: {
70 | path: webpackPaths.dllPath,
71 | },
72 | },
73 | }),
74 | ],
75 | });
76 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.renderer.dev.ts:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import fs from 'fs';
3 | import webpack from 'webpack';
4 | import HtmlWebpackPlugin from 'html-webpack-plugin';
5 | import chalk from 'chalk';
6 | import { merge } from 'webpack-merge';
7 | import { spawn, execSync } from 'child_process';
8 | import baseConfig from './webpack.config.base';
9 | import webpackPaths from './webpack.paths';
10 | import checkNodeEnv from '../scripts/check-node-env';
11 | import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
12 |
13 | // When an ESLint server is running, we can't set the NODE_ENV so we'll check if it's
14 | // at the dev webpack config is not accidentally run in a production environment
15 | if (process.env.NODE_ENV === 'production') {
16 | checkNodeEnv('development');
17 | }
18 |
19 | const port = process.env.PORT || 1212;
20 | const manifest = path.resolve(webpackPaths.dllPath, 'renderer.json');
21 | const requiredByDLLConfig = module.parent.filename.includes(
22 | 'webpack.config.renderer.dev.dll'
23 | );
24 |
25 | /**
26 | * Warn if the DLL is not built
27 | */
28 | if (
29 | !requiredByDLLConfig &&
30 | !(fs.existsSync(webpackPaths.dllPath) && fs.existsSync(manifest))
31 | ) {
32 | console.log(
33 | chalk.black.bgYellow.bold(
34 | 'The DLL files are missing. Sit back while we build them for you with "npm run build-dll"'
35 | )
36 | );
37 | execSync('npm run postinstall');
38 | }
39 |
40 | export default merge(baseConfig, {
41 | devtool: 'inline-source-map',
42 |
43 | mode: 'development',
44 |
45 | target: ['web', 'electron-renderer'],
46 |
47 | entry: [
48 | `webpack-dev-server/client?http://localhost:${port}/dist`,
49 | 'webpack/hot/only-dev-server',
50 | 'core-js',
51 | 'regenerator-runtime/runtime',
52 | path.join(webpackPaths.srcRendererPath, 'index.tsx'),
53 | ],
54 |
55 | output: {
56 | path: webpackPaths.distRendererPath,
57 | publicPath: '/',
58 | filename: 'renderer.dev.js',
59 | library: {
60 | type: 'umd',
61 | },
62 | },
63 |
64 | module: {
65 | rules: [
66 | {
67 | test: /\.s?css$/,
68 | use: [
69 | 'style-loader',
70 | {
71 | loader: 'css-loader',
72 | options: {
73 | modules: true,
74 | sourceMap: true,
75 | importLoaders: 1,
76 | },
77 | },
78 | 'sass-loader',
79 | ],
80 | include: /\.module\.s?(c|a)ss$/,
81 | },
82 | {
83 | test: /\.s?css$/,
84 | use: ['style-loader', 'css-loader', 'sass-loader'],
85 | exclude: /\.module\.s?(c|a)ss$/,
86 | },
87 | // Fonts
88 | {
89 | test: /\.(woff|woff2|eot|ttf|otf)$/i,
90 | type: 'asset/resource',
91 | },
92 | // Images
93 | {
94 | test: /\.(png|svg|jpg|jpeg|gif)$/i,
95 | type: 'asset/resource',
96 | },
97 | ],
98 | },
99 | plugins: [
100 | requiredByDLLConfig
101 | ? null
102 | : new webpack.DllReferencePlugin({
103 | context: webpackPaths.dllPath,
104 | manifest: require(manifest),
105 | sourceType: 'var',
106 | }),
107 |
108 | new webpack.NoEmitOnErrorsPlugin(),
109 |
110 | /**
111 | * Create global constants which can be configured at compile time.
112 | *
113 | * Useful for allowing different behaviour between development builds and
114 | * release builds
115 | *
116 | * NODE_ENV should be production so that modules do not perform certain
117 | * development checks
118 | *
119 | * By default, use 'development' as NODE_ENV. This can be overriden with
120 | * 'staging', for example, by changing the ENV variables in the npm scripts
121 | */
122 | new webpack.EnvironmentPlugin({
123 | NODE_ENV: 'development',
124 | }),
125 |
126 | new webpack.LoaderOptionsPlugin({
127 | debug: true,
128 | }),
129 |
130 | new ReactRefreshWebpackPlugin(),
131 |
132 | new HtmlWebpackPlugin({
133 | filename: path.join('index.html'),
134 | template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
135 | minify: {
136 | collapseWhitespace: true,
137 | removeAttributeQuotes: true,
138 | removeComments: true,
139 | },
140 | isBrowser: false,
141 | env: process.env.NODE_ENV,
142 | isDevelopment: process.env.NODE_ENV !== 'production',
143 | nodeModules: webpackPaths.appNodeModulesPath,
144 | }),
145 | ],
146 |
147 | node: {
148 | __dirname: false,
149 | __filename: false,
150 | },
151 |
152 | devServer: {
153 | port,
154 | compress: true,
155 | hot: true,
156 | headers: { 'Access-Control-Allow-Origin': '*' },
157 | static: {
158 | publicPath: '/',
159 | },
160 | client: {
161 | logging: 'none'
162 | },
163 | historyApiFallback: {
164 | verbose: true,
165 | disableDotRule: false,
166 | },
167 | onBeforeSetupMiddleware() {
168 | console.log('Starting Main Process...');
169 | spawn('npm', ['run', 'start:main'], {
170 | shell: true,
171 | env: process.env,
172 | stdio: 'inherit',
173 | })
174 | .on('close', (code) => process.exit(code))
175 | .on('error', (spawnError) => console.error(spawnError));
176 | },
177 | },
178 | });
179 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.config.renderer.prod.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Build config for electron renderer process
3 | */
4 |
5 | import path from 'path';
6 | import webpack from 'webpack';
7 | import HtmlWebpackPlugin from 'html-webpack-plugin';
8 | import MiniCssExtractPlugin from 'mini-css-extract-plugin';
9 | import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
10 | import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
11 | import { merge } from 'webpack-merge';
12 | import TerserPlugin from 'terser-webpack-plugin';
13 | import baseConfig from './webpack.config.base';
14 | import webpackPaths from './webpack.paths';
15 | import checkNodeEnv from '../scripts/check-node-env';
16 | import deleteSourceMaps from '../scripts/delete-source-maps';
17 |
18 | checkNodeEnv('production');
19 | deleteSourceMaps();
20 |
21 | const devtoolsConfig =
22 | process.env.DEBUG_PROD === 'true'
23 | ? {
24 | devtool: 'source-map',
25 | }
26 | : {};
27 |
28 | export default merge(baseConfig, {
29 | ...devtoolsConfig,
30 |
31 | mode: 'production',
32 |
33 | target: ['web', 'electron-renderer'],
34 |
35 | entry: [
36 | 'core-js',
37 | 'regenerator-runtime/runtime',
38 | path.join(webpackPaths.srcRendererPath, 'index.tsx'),
39 | ],
40 |
41 | output: {
42 | path: webpackPaths.distRendererPath,
43 | publicPath: './',
44 | filename: 'renderer.js',
45 | library: {
46 | type: 'umd',
47 | },
48 | },
49 |
50 | module: {
51 | rules: [
52 | {
53 | test: /\.s?(a|c)ss$/,
54 | use: [
55 | MiniCssExtractPlugin.loader,
56 | {
57 | loader: 'css-loader',
58 | options: {
59 | modules: true,
60 | sourceMap: true,
61 | importLoaders: 1,
62 | },
63 | },
64 | 'sass-loader',
65 | ],
66 | include: /\.module\.s?(c|a)ss$/,
67 | },
68 | {
69 | test: /\.s?(a|c)ss$/,
70 | use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'],
71 | exclude: /\.module\.s?(c|a)ss$/,
72 | },
73 | // Fonts
74 | {
75 | test: /\.(woff|woff2|eot|ttf|otf)$/i,
76 | type: 'asset/resource',
77 | },
78 | // Images
79 | {
80 | test: /\.(png|svg|jpg|jpeg|gif)$/i,
81 | type: 'asset/resource',
82 | },
83 | ],
84 | },
85 |
86 | optimization: {
87 | minimize: true,
88 | minimizer: [
89 | new TerserPlugin({
90 | parallel: true,
91 | }),
92 | new CssMinimizerPlugin(),
93 | ],
94 | },
95 |
96 | plugins: [
97 | /**
98 | * Create global constants which can be configured at compile time.
99 | *
100 | * Useful for allowing different behaviour between development builds and
101 | * release builds
102 | *
103 | * NODE_ENV should be production so that modules do not perform certain
104 | * development checks
105 | */
106 | new webpack.EnvironmentPlugin({
107 | NODE_ENV: 'production',
108 | DEBUG_PROD: false,
109 | }),
110 |
111 | new MiniCssExtractPlugin({
112 | filename: 'style.css',
113 | }),
114 |
115 | new BundleAnalyzerPlugin({
116 | analyzerMode: process.env.ANALYZE === 'true' ? 'server' : 'disabled',
117 | }),
118 |
119 | new HtmlWebpackPlugin({
120 | filename: 'index.html',
121 | template: path.join(webpackPaths.srcRendererPath, 'index.ejs'),
122 | minify: {
123 | collapseWhitespace: true,
124 | removeAttributeQuotes: true,
125 | removeComments: true,
126 | },
127 | isBrowser: false,
128 | isDevelopment: process.env.NODE_ENV !== 'production',
129 | }),
130 | ],
131 | });
132 |
--------------------------------------------------------------------------------
/.erb/configs/webpack.paths.ts:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | const rootPath = path.join(__dirname, '../..');
4 |
5 | const dllPath = path.join(__dirname, '../dll');
6 |
7 | const srcPath = path.join(rootPath, 'src');
8 | const srcMainPath = path.join(srcPath, 'main');
9 | const srcRendererPath = path.join(srcPath, 'renderer');
10 |
11 | const releasePath = path.join(rootPath, 'release');
12 | const appPath = path.join(releasePath, 'app');
13 | const appPackagePath = path.join(appPath, 'package.json');
14 | const appNodeModulesPath = path.join(appPath, 'node_modules');
15 | const srcNodeModulesPath = path.join(srcPath, 'node_modules');
16 |
17 | const distPath = path.join(appPath, 'dist');
18 | const distMainPath = path.join(distPath, 'main');
19 | const distRendererPath = path.join(distPath, 'renderer');
20 |
21 | const buildPath = path.join(releasePath, 'build');
22 |
23 | export default {
24 | rootPath,
25 | dllPath,
26 | srcPath,
27 | srcMainPath,
28 | srcRendererPath,
29 | releasePath,
30 | appPath,
31 | appPackagePath,
32 | appNodeModulesPath,
33 | srcNodeModulesPath,
34 | distPath,
35 | distMainPath,
36 | distRendererPath,
37 | buildPath,
38 | };
39 |
--------------------------------------------------------------------------------
/.erb/img/erb-banner.svg:
--------------------------------------------------------------------------------
1 |
33 |
--------------------------------------------------------------------------------
/.erb/img/erb-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AnthonyGress/Android-Toolkit/f45f5cb66d5a2de2b9a72eb7811be8996811c676/.erb/img/erb-logo.png
--------------------------------------------------------------------------------
/.erb/mocks/fileMock.js:
--------------------------------------------------------------------------------
1 | export default 'test-file-stub';
2 |
--------------------------------------------------------------------------------
/.erb/scripts/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "no-console": "off",
4 | "global-require": "off",
5 | "import/no-dynamic-require": "off",
6 | "import/no-extraneous-dependencies": "off"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/.erb/scripts/check-build-exists.ts:
--------------------------------------------------------------------------------
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 | import webpackPaths from '../configs/webpack.paths';
6 |
7 | const mainPath = path.join(webpackPaths.distMainPath, 'main.js');
8 | const rendererPath = path.join(webpackPaths.distRendererPath, 'renderer.js');
9 |
10 | if (!fs.existsSync(mainPath)) {
11 | throw new Error(
12 | chalk.whiteBright.bgRed.bold(
13 | 'The main process is not built yet. Build it by running "npm run build:main"'
14 | )
15 | );
16 | }
17 |
18 | if (!fs.existsSync(rendererPath)) {
19 | throw new Error(
20 | chalk.whiteBright.bgRed.bold(
21 | 'The renderer process is not built yet. Build it by running "npm run build:renderer"'
22 | )
23 | );
24 | }
25 |
--------------------------------------------------------------------------------
/.erb/scripts/check-native-dep.js:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import chalk from 'chalk';
3 | import { execSync } from 'child_process';
4 | import { dependencies } from '../../package.json';
5 |
6 | if (dependencies) {
7 | const dependenciesKeys = Object.keys(dependencies);
8 | const nativeDeps = fs
9 | .readdirSync('node_modules')
10 | .filter((folder) => fs.existsSync(`node_modules/${folder}/binding.gyp`));
11 | if (nativeDeps.length === 0) {
12 | process.exit(0);
13 | }
14 | try {
15 | // Find the reason for why the dependency is installed. If it is installed
16 | // because of a devDependency then that is okay. Warn when it is installed
17 | // because of a dependency
18 | const { dependencies: dependenciesObject } = JSON.parse(
19 | execSync(`npm ls ${nativeDeps.join(' ')} --json`).toString()
20 | );
21 | const rootDependencies = Object.keys(dependenciesObject);
22 | const filteredRootDependencies = rootDependencies.filter((rootDependency) =>
23 | dependenciesKeys.includes(rootDependency)
24 | );
25 | if (filteredRootDependencies.length > 0) {
26 | const plural = filteredRootDependencies.length > 1;
27 | console.log(`
28 | ${chalk.whiteBright.bgYellow.bold(
29 | 'Webpack does not work with native dependencies.'
30 | )}
31 | ${chalk.bold(filteredRootDependencies.join(', '))} ${
32 | plural ? 'are native dependencies' : 'is a native dependency'
33 | } and should be installed inside of the "./release/app" folder.
34 | First, uninstall the packages from "./package.json":
35 | ${chalk.whiteBright.bgGreen.bold('npm uninstall your-package')}
36 | ${chalk.bold(
37 | 'Then, instead of installing the package to the root "./package.json":'
38 | )}
39 | ${chalk.whiteBright.bgRed.bold('npm install your-package')}
40 | ${chalk.bold('Install the package to "./release/app/package.json"')}
41 | ${chalk.whiteBright.bgGreen.bold('cd ./release/app && npm install your-package')}
42 | Read more about native dependencies at:
43 | ${chalk.bold(
44 | 'https://electron-react-boilerplate.js.org/docs/adding-dependencies/#module-structure'
45 | )}
46 | `);
47 | process.exit(1);
48 | }
49 | } catch (e) {
50 | console.log('Native dependencies could not be checked');
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/.erb/scripts/check-node-env.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.log(
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 |
--------------------------------------------------------------------------------
/.erb/scripts/check-port-in-use.js:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 | import detectPort from 'detect-port';
3 |
4 | const port = process.env.PORT || '1212';
5 |
6 | detectPort(port, (err, availablePort) => {
7 | if (port !== String(availablePort)) {
8 | throw new Error(
9 | chalk.whiteBright.bgRed.bold(
10 | `Port "${port}" on "localhost" is already in use. Please use another port. ex: PORT=4343 npm start`
11 | )
12 | );
13 | } else {
14 | process.exit(0);
15 | }
16 | });
17 |
--------------------------------------------------------------------------------
/.erb/scripts/clean.js:
--------------------------------------------------------------------------------
1 | import rimraf from 'rimraf';
2 | import webpackPaths from '../configs/webpack.paths.ts';
3 | import process from 'process';
4 |
5 | const args = process.argv.slice(2);
6 | const commandMap = {
7 | dist: webpackPaths.distPath,
8 | release: webpackPaths.releasePath,
9 | dll: webpackPaths.dllPath,
10 | };
11 |
12 | args.forEach((x) => {
13 | const pathToRemove = commandMap[x];
14 | if (pathToRemove !== undefined) {
15 | rimraf.sync(pathToRemove);
16 | }
17 | });
18 |
--------------------------------------------------------------------------------
/.erb/scripts/delete-source-maps.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import rimraf from 'rimraf';
3 | import webpackPaths from '../configs/webpack.paths';
4 |
5 | export default function deleteSourceMaps() {
6 | rimraf.sync(path.join(webpackPaths.distMainPath, '*.js.map'));
7 | rimraf.sync(path.join(webpackPaths.distRendererPath, '*.js.map'));
8 | }
9 |
--------------------------------------------------------------------------------
/.erb/scripts/electron-rebuild.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import { execSync } from 'child_process';
3 | import fs from 'fs';
4 | import { dependencies } from '../../release/app/package.json';
5 | import webpackPaths from '../configs/webpack.paths';
6 |
7 | if (
8 | Object.keys(dependencies || {}).length > 0 &&
9 | fs.existsSync(webpackPaths.appNodeModulesPath)
10 | ) {
11 | const electronRebuildCmd =
12 | '../../node_modules/.bin/@electron-rebuild --parallel --force --types prod,dev,optional --module-dir .';
13 | const cmd =
14 | process.platform === 'win32'
15 | ? electronRebuildCmd.replace(/\//g, '\\')
16 | : electronRebuildCmd;
17 | execSync(cmd, {
18 | cwd: webpackPaths.appPath,
19 | stdio: 'inherit',
20 | });
21 | }
22 |
--------------------------------------------------------------------------------
/.erb/scripts/link-modules.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import webpackPaths from '../configs/webpack.paths';
3 |
4 | const srcNodeModulesPath = webpackPaths.srcNodeModulesPath;
5 | const appNodeModulesPath = webpackPaths.appNodeModulesPath
6 |
7 | if (!fs.existsSync(srcNodeModulesPath) && fs.existsSync(appNodeModulesPath)) {
8 | fs.symlinkSync(appNodeModulesPath, srcNodeModulesPath, 'junction');
9 | }
10 |
--------------------------------------------------------------------------------
/.erb/scripts/notarize.js:
--------------------------------------------------------------------------------
1 | const { notarize } = require('@electron/notarize');
2 | const { build } = require('../../package.json');
3 |
4 | exports.default = async function notarizeMacos(context) {
5 | const { electronPlatformName, appOutDir } = context;
6 | if (electronPlatformName !== 'darwin') {
7 | return;
8 | }
9 |
10 | if (!process.env.CI) {
11 | console.warn('Skipping notarizing step. Packaging is not running in CI');
12 | return;
13 | }
14 |
15 | if (!('APPLE_ID' in process.env && 'APPLE_ID_PASS' in process.env)) {
16 | console.warn('Skipping notarizing step. APPLE_ID and APPLE_ID_PASS env variables must be set');
17 | return;
18 | }
19 |
20 | const appName = context.packager.appInfo.productFilename;
21 |
22 | await notarize({
23 | appBundleId: build.appId,
24 | appPath: `${appOutDir}/${appName}.app`,
25 | appleId: process.env.APPLE_ID,
26 | appleIdPassword: process.env.APPLE_ID_PASS,
27 | });
28 | };
29 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Coverage directory used by tools like istanbul
11 | coverage
12 | .eslintcache
13 |
14 | # Dependency directory
15 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
16 | node_modules
17 |
18 | # OSX
19 | .DS_Store
20 |
21 | release/app/dist
22 | release/build
23 | .erb/dll
24 |
25 | .idea
26 | npm-debug.log.*
27 | *.css.d.ts
28 | *.sass.d.ts
29 | *.scss.d.ts
30 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: { 'shared-node-browser': true, node: true, browser: true },
3 | extends: [
4 | 'eslint:recommended',
5 | 'plugin:@typescript-eslint/eslint-recommended',
6 | 'plugin:@typescript-eslint/recommended',
7 | ],
8 | plugins: ['import', 'react'],
9 | rules: {
10 | 'import/no-extraneous-dependencies': 'off',
11 | 'react/react-in-jsx-scope': 'off',
12 | 'no-console': 'off',
13 | 'global-require': 'off',
14 | 'import/no-dynamic-require': 'off',
15 | indent: ['warn', 4],
16 | quotes: ['warn', 'single'],
17 | 'prettier/prettier': 0,
18 | 'object-curly-spacing': ['warn', 'always'],
19 | '@typescript-eslint/ban-types': 'off',
20 | '@typescript-eslint/no-var-requires': 'off',
21 | '@typescript-eslint/no-non-null-assertion': 'off',
22 | 'semi': 'warn'
23 | },
24 | parserOptions: {
25 | ecmaVersion: 2021,
26 | sourceType: 'module',
27 | project: './tsconfig.json',
28 | tsconfigRootDir: __dirname,
29 | createDefaultProgram: true,
30 | },
31 | settings: {
32 | 'import/resolver': {
33 | // See https://github.com/benmosher/eslint-plugin-import/issues/1396#issuecomment-575727774 for line below
34 | node: {},
35 | webpack: {
36 | config: require.resolve(
37 | './.erb/configs/webpack.config.eslint.ts'
38 | ),
39 | },
40 | },
41 | 'import/parsers': {
42 | '@typescript-eslint/parser': ['.ts', '.tsx'],
43 | },
44 | },
45 | };
46 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text eol=lf
2 | *.exe binary
3 | *.png binary
4 | *.jpg binary
5 | *.jpeg binary
6 | *.ico binary
7 | *.icns binary
8 | *.eot binary
9 | *.otf binary
10 | *.ttf binary
11 | *.woff binary
12 | *.woff2 binary
13 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/1-Bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: You're having technical issues. 🐞
4 | labels: 'bug'
5 | ---
6 |
7 |
8 |
9 | ## Prerequisites
10 |
11 | ## Expected Behavior
12 |
13 |
14 |
15 | ## Current Behavior
16 |
17 |
18 |
19 | ## Steps to Reproduce
20 |
21 |
22 |
23 |
24 | 1.
25 |
26 | 2.
27 |
28 | 3.
29 |
30 | 4.
31 |
32 | ## Possible Solution (Not obligatory)
33 |
34 |
35 |
36 | ## Context
37 |
38 |
39 |
40 |
41 |
42 | ## Your Environment
43 |
44 |
45 |
46 | - App version :
47 | - Device (Phone, FireTV, AndroidTV) and Android version :
48 | - Link to your project :
49 |
50 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/2-Question.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Question
3 | about: Ask a question.
4 | labels: 'question'
5 | ---
6 |
7 | ## Summary
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/3-Feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: You want something added to the app.
4 | labels: 'enhancement'
5 | ---
6 |
7 |
--------------------------------------------------------------------------------
/.github/config.yml:
--------------------------------------------------------------------------------
1 | requiredHeaders:
2 | - Prerequisites
3 | - Expected Behavior
4 | - Current Behavior
5 | - Possible Solution
6 | - Your Environment
7 |
--------------------------------------------------------------------------------
/.github/stale.yml:
--------------------------------------------------------------------------------
1 | # Number of days of inactivity before an issue becomes stale
2 | daysUntilStale: 60
3 | # Number of days of inactivity before a stale issue is closed
4 | daysUntilClose: 7
5 | # Issues with these labels will never be considered stale
6 | exemptLabels:
7 | - discussion
8 | - security
9 | # Label to use when marking an issue as stale
10 | staleLabel: wontfix
11 | # Comment to post when marking an issue as stale. Set to `false` to disable
12 | markComment: >
13 | This issue has been automatically marked as stale because it has not had
14 | recent activity. It will be closed if no further activity occurs. Thank you
15 | for your contributions.
16 | # Comment to post when closing a stale issue. Set to `false` to disable
17 | closeComment: false
18 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | publish:
10 | runs-on: ${{ matrix.os }}
11 |
12 | strategy:
13 | matrix:
14 | os: [macos-latest]
15 |
16 | steps:
17 | - name: Checkout git repo
18 | uses: actions/checkout@v4
19 |
20 | - name: Install Node and NPM
21 | uses: actions/setup-node@v4
22 | with:
23 | node-version: 20
24 |
25 | - name: Install dependencies
26 | run: |
27 | npm install
28 |
29 | - name: Publish releases
30 | env:
31 | # These values are used for auto updates signing
32 | # APPLE_ID: ${{ secrets.APPLE_ID }}
33 | # APPLE_ID_PASS: ${{ secrets.APPLE_ID_PASS }}
34 | # CSC_LINK: ${{ secrets.CSC_LINK }}
35 | # CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
36 | CSC_IDENTITY_AUTO_DISCOVERY: false
37 | # This is used for uploading release assets to github
38 | GITHUB_TOKEN: ${{ secrets.TOKEN }}
39 | run: |
40 | npm run postinstall
41 | npm run build
42 | npm run release
43 |
--------------------------------------------------------------------------------
/.github/workflows/quality-check.yml:
--------------------------------------------------------------------------------
1 | name: Code Quality Check
2 |
3 | on:
4 | pull_request:
5 | branches: [ main ]
6 |
7 | workflow_dispatch:
8 |
9 | jobs:
10 | run-quality-check:
11 | runs-on: ubuntu-latest
12 | env:
13 | CI: false
14 |
15 | steps:
16 | - uses: actions/checkout@v4
17 |
18 | - name: Install dependencies run Lint and Test
19 | run: |
20 | npm install
21 | npm run lint
22 | npm run build
23 | npm test
24 |
25 | - name: Get all git tags
26 | run: git fetch --all --tags
27 |
28 | - name: Version Check
29 | uses: thebongy/version-check@v1
30 | with:
31 | file: release/app/package.json
32 | tagFormat: v${version}
33 | id: version_check
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Coverage directory used by tools like istanbul
11 | coverage
12 | .eslintcache
13 |
14 | # Dependency directory
15 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
16 | node_modules
17 |
18 | # OSX
19 | .DS_Store
20 |
21 | release/app/dist
22 | release/build
23 | .erb/dll
24 |
25 | .idea
26 | npm-debug.log.*
27 | *.css.d.ts
28 | *.sass.d.ts
29 | *.scss.d.ts
30 | .env
31 | package-lock.json
32 | .vscode
33 | .idea
34 | apks
35 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx lint-staged
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015-present Anthony Gress
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Android-Toolkit
2 |
3 | 
4 |
5 | # Install
6 |
7 | ## Mac & Linux
8 |
9 | Copy and paste this into the Terminal App to install.
10 |
11 | ```
12 | /bin/bash -c "$(curl -sL https://raw.githubusercontent.com/AnthonyGress/Android-Toolkit/main/install.sh)"
13 | ```
14 | ---
15 |
16 | ## Windows
17 |
18 | ## Download Latest: [Release](https://github.com/anthonygress/Android-Toolkit/releases/latest/download/Android-toolkit-setup.exe)
19 |
20 |
21 | Use the latest released installer named `Android-Toolkit-Setup.exe` to get started.
22 |
23 |
24 |
25 | # Usage
26 | ## Android TV / FireTV
27 | 1. Make sure you are on the same WiFi network as your android device.
28 | 2. Find the IP address of your device.
29 | On FireTV: Firestick Settings > My Fire TV > About > Network
30 | 3. Go to Device Settings and turn on ADB debugging and Install Apps from Unknown Sources.
31 | On FireTV: Settings > My Fire TV > Developer Options
32 | 4. Enter IP address into __ADB Connection Tools__ and click "Connect" or press the enter key.
33 |
34 |
35 | ## Phones/Tablets with Android 11 or higher
36 |
37 | ### For wired adb connection, you will need to:
38 | 1. enable developer mode by tapping on the build number in the about settings
39 | 2. enable usb debugging.
40 | 3. plug in your device via usb
41 |
42 | ### For wireless connection you will need to:
43 | 1. enable developer mode
44 | 2. enable usb debugging
45 | 3. wireless debugging.
46 | 4. Under the wireless debugging settings, you will need to tap pair device with pairing code.
47 | 5. Enter the pairing ipAddress:port and the pairing code in Android Toolkit.
48 | 6. Once paired, you will need to back out and use the ADB Connect section to connect to the IP address and port listed under wireless debugging.
49 |
50 | ### To enable file transfer with your connected computer:
51 | 1. Plug your device in via USB
52 | 2. Tap to notification on your phone/tablet that says "charging via USB"
53 | 3. Choose the option for File transfer / Android Auto.
54 |
55 |
56 |
57 | # APK Tools
58 |
59 | ## Install Single APK
60 |
61 | You can install any APK file from your computer directly on to your android device.
62 |
63 |
64 | ## Batch Install
65 | Installs ALL files with .apk extension in the selected directory onto your device.
66 |
67 |
68 | ## Quick Install Apps
69 | One click install for selected popular modded apps.
70 |
71 |
72 |
73 | ## TV Apps
74 |
75 | SmartTube - [https://github.com/yuliskov/SmartTubeNext/blob/master/README.md](https://github.com/yuliskov/SmartTubeNext/blob/master/README.md)
76 |
77 | Launcher Manager (FireTV) - [https://forum.xda-developers.com/t/app-firetv-noroot-launcher-manager-change-launcher-without-root.4176349/](https://forum.xda-developers.com/t/app-firetv-noroot-launcher-manager-change-launcher-without-root.4176349/)
78 |
79 | Wolf Launcher - [https://www.techdoctoruk.com/tutorials/block-android-tv-adverts-with-wolf-launcher/](https://www.techdoctoruk.com/tutorials/block-android-tv-adverts-with-wolf-launcher/)
80 |
81 |
82 | ## Mobile Apps (phone/tables)
83 | > Note: Delete the original play store app before installing
84 |
85 | Revanced - [https://revanced.app/](https://revanced.app/)
86 |
87 | To learn more about what each patch does, open the ReVanced Manager app and select your application, or visit the website for [ReVanced Patches](https://revanced.app/patches)
88 |
89 | The Infinity for Reddit patch is from [https://github.com/KhoalaS/Infinity-For-Reddit](https://github.com/KhoalaS/Infinity-For-Reddit)
90 |
91 | Simply click the button to download and install the app directly on your device.
92 |
93 | For spotify/reddit you may need to login with your username and password if signing in with google doesn't work. Youtube and Youtube Music need MicroG installed to login to your google account.
94 |
95 |
96 |
97 | # ReVanced Tools
98 |
99 | Download each of the apps in the list. Then open ReVanced and patch your youtube app. To revert at any time, simply uninstall the app and use the original youtube app from the play store.
100 |
101 | You can get links to open in the ReVanced app by going into settings > apps > youtube > open by default and unchecking all the options. Then delete data, disable/delete the app, then restart.
102 |
103 | To enable links to open in Youtube ReVanced, go to settings > apps > Youtube ReVanced > open by default and select all the options, then restart.
104 |
105 | > NOTE: On my pixel device it seems any youtube links from google chrome will try to open in the stock youtube app, or take you to the play store to install/enable it. This doesn't seem to happen from the google app.
106 |
107 | Prebuilt apks - [Revanced APKs](https://github.com/revanced-apks/build-apps/releases)
108 |
109 |
110 |
111 | # FireTV Tools
112 |
113 | ## Set Screensaver
114 | Lets you set a custom screensaver app. I have included a modified application in this repo called "Website Daydream" that changes the default wallpaper to the website https://clients3.google.com/cast/chromecast/home
115 |
116 | After installing Website Daydream, install the application called Activity launcher (https://www.f-droid.org/en/packages/de.szalkowski.activitylauncher/). Open it, and just touch the website daydream app in order for it to work.
117 |
118 |
119 |
120 | ## Check Screensaver
121 | Gets the current values for your screensaver and returns them.
122 |