Skip to content

Commit

Permalink
feat: Support change the Nodejs installation directory.
Browse files Browse the repository at this point in the history
Signed-off-by: The1111mp <The1111mp@outlook.com>
  • Loading branch information
1111mp committed Nov 17, 2023
1 parent d92b5ab commit 87f765e
Show file tree
Hide file tree
Showing 16 changed files with 272 additions and 53 deletions.
1 change: 1 addition & 0 deletions @types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ declare global {
interface Setting {
locale: string;
theme: Themes;
directory: string;
mirror: string;
}

Expand Down
12 changes: 12 additions & 0 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@
"message": "Mirror Url",
"description": "The text of the Mirror Url"
},
"Installation-Directory": {
"message": "Installation Directory",
"description": "The text of the Installation Directory"
},
"Installation-Directory-tip": {
"message": "Please note that nvm-desktop does not keep track of all your used directories. This means that every time you change the installation directory, you need to re-download Nodejs.",
"description": "The text of the Installation-Directory-tip"
},
"For-example": {
"message": "For example",
"description": "The text of the For example"
Expand Down Expand Up @@ -351,6 +359,10 @@
"message": "Please select your project",
"description": "The text of the Project-Select"
},
"Directory-Select": {
"message": "Please select your directory",
"description": "The text of the Directory-Select"
},
"Whats-new": {
"message": "What's new",
"description": "The text of the Whats-new"
Expand Down
12 changes: 12 additions & 0 deletions _locales/zh_CN/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@
"message": "镜像地址",
"description": "The text of the Mirror Url"
},
"Installation-Directory": {
"message": "安装目录",
"description": "The text of the Installation Directory"
},
"Installation-Directory-tip": {
"message": "请注意,nvm-desktop 不会跟踪您所使用过的所有的目录,这意味着您每次更改安装目录之后都需要重新下载 Nodejs",
"description": "The text of the Installation-Directory-tip"
},
"For-example": {
"message": "例如",
"description": "The text of the For example"
Expand Down Expand Up @@ -351,6 +359,10 @@
"message": "请选择您的项目",
"description": "The text of the Project-Select"
},
"Directory-Select": {
"message": "请选择您的目录",
"description": "The text of the Directory-Select"
},
"Whats-new": {
"message": "更新日志",
"description": "The text of the Whats-new"
Expand Down
14 changes: 6 additions & 8 deletions src/main/deps/all-node-versions/cache/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,16 @@ export async function getCache({
return versions;
}

export async function getInstalledVersions(): Promise<string[]> {
if (!(await pathExists(INSTALL_DIR))) return [];
export async function getInstalledVersions(
path: string = INSTALL_DIR,
): Promise<string[]> {
if (!(await pathExists(path))) return [];

const contents = await readdir(INSTALL_DIR);
const contents = await readdir(path);
const exists = await Promise.all(
contents.map(async (version) => {
return await pathExists(
join(
INSTALL_DIR,
version,
platform === 'win32' ? 'node.exe' : 'bin/node',
),
join(path, version, platform === 'win32' ? 'node.exe' : 'bin/node'),
);
}),
);
Expand Down
10 changes: 8 additions & 2 deletions src/main/deps/all-node-versions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,17 @@ export const allNodeVersions = async (options: Options = {}) => {
return versionsInfo;
};

export async function allInstalledNodeVersions(refresh: boolean = false) {
export async function allInstalledNodeVersions({
path,
refresh = false,
}: {
path?: string;
refresh?: boolean;
}) {
if (installedVersions !== void 0 && refresh !== true)
return installedVersions;

const versions = await getInstalledVersions();
const versions = await getInstalledVersions(path);

installedVersions = versions;

Expand Down
61 changes: 42 additions & 19 deletions src/main/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,13 @@ app.on('window-all-closed', () => {
app
.whenReady()
.then(async () => {
const [code, settingFromCache, iVersions] = await Promise.all([
const [code, settingFromCache] = await Promise.all([
updateSchema(),
getSetting(),
allInstalledNodeVersions(),
]);
const iVersions = await allInstalledNodeVersions({
path: settingFromCache.directory,
});

if (!setting) setting = settingFromCache;
if (!installedVersions)
Expand Down Expand Up @@ -354,12 +356,21 @@ Promise.resolve().then(() => {
menuBuilder.buildMenu(locale.i18n);
buildTray();
}

if (data.directory !== setting.directory) {
const versions = await allInstalledNodeVersions({
path: data.directory,
refresh: true,
});

installedVersions = versions.sort((version1, version2) =>
gt(version2, version1) ? 1 : -1,
);
buildTray();
}

setting = { ...setting, ...data };
await setSetting({
locale: setting.locale,
theme: setting.theme,
mirror: setting.mirror,
});
await setSetting(setting);
return;
},
);
Expand Down Expand Up @@ -411,7 +422,10 @@ Promise.resolve().then(() => {
async (_event, refresh: boolean = false) => {
if (!refresh) return installedVersions;

const versions = await allInstalledNodeVersions(refresh);
const versions = await allInstalledNodeVersions({
path: setting.directory,
refresh,
});

installedVersions = versions.sort((version1, version2) =>
gt(version2, version1) ? 1 : -1,
Expand All @@ -429,6 +443,7 @@ Promise.resolve().then(() => {

try {
const result = await getNode(version, {
output: setting.directory,
mirror: setting.mirror,
signal: abortController.signal,
onProgress: (data) => {
Expand All @@ -447,7 +462,7 @@ Promise.resolve().then(() => {
ipcMain.handle(
'uninstall-node-version',
async (_event, version: string, current: boolean = false) => {
return uninstallVersion(version, current);
return uninstallVersion({ path: setting.directory, version, current });
},
);

Expand All @@ -468,19 +483,27 @@ Promise.resolve().then(() => {
event.returnValue = nativeTheme.shouldUseDarkColors ? 'dark' : 'light';
});

ipcMain.handle('open-folder-selecter', async () => {
const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow!, {
title: locale.i18n('Project-Select') as string,
properties: ['openDirectory'],
});
ipcMain.handle(
'open-folder-selecter',
async (
_event,
{ title, project }: { title: string; project?: boolean },
) => {
const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow!, {
title,
properties: ['openDirectory', 'createDirectory', 'showHiddenFiles'],
});

if (canceled) return { canceled, filePaths };
if (canceled) return { canceled, filePaths };

const [path] = filePaths;
const version = await getVersion(path);
const [path] = filePaths;

return { canceled, filePaths, version };
});
if (!project) return { canceled, filePaths };

const version = await getVersion(path);
return { canceled, filePaths, version };
},
);

ipcMain.handle('get-projects', async (_event, load: boolean = false) => {
return getProjects(load);
Expand Down
12 changes: 9 additions & 3 deletions src/main/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,15 @@ const electronHandler = {
onThemeChanged = callback;
},

openFolderSelecter: () =>
ipcRenderer.invoke('open-folder-selecter') as Promise<
OpenDialogReturnValue & { version: string }
openFolderSelecter: ({
title,
project = false,
}: {
title: string;
project?: boolean;
}) =>
ipcRenderer.invoke('open-folder-selecter', { title, project }) as Promise<
OpenDialogReturnValue & { version?: string }
>,
getProjects: (load: boolean = false) =>
ipcRenderer.invoke('get-projects', load) as Promise<Nvmd.Project[]>,
Expand Down
5 changes: 4 additions & 1 deletion src/main/utils/setting.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import { pathExists, readJson, writeJson } from 'fs-extra';
import { app } from 'electron';
import { SETTING_JSONFILE } from '../constants';
import { INSTALL_DIR, SETTING_JSONFILE } from '../constants';
import { Themes } from '../../types';

export async function getSetting(): Promise<Nvmd.Setting> {
if (!(await pathExists(SETTING_JSONFILE)))
return {
locale: app.getLocale().startsWith('en') ? 'en' : 'zh-CN',
theme: Themes.System,
directory: INSTALL_DIR,
mirror: 'https://nodejs.org/dist',
};

const setting = await readJson(SETTING_JSONFILE, { throws: false });
if (!setting.directory) setting.directory = INSTALL_DIR;
return (
setting || {
locale: app.getLocale().startsWith('en') ? 'en' : 'zh-CN',
theme: Themes.System,
directory: INSTALL_DIR,
mirror: 'https://nodejs.org/dist',
}
);
Expand Down
17 changes: 11 additions & 6 deletions src/main/utils/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ export async function setCurrentVersion(newVersion: string): Promise<void> {
return;
}

export async function uninstallVersion(
version: string,
current: boolean = false,
) {
export async function uninstallVersion({
path = INSTALL_DIR,
version,
current = false,
}: {
path?: string;
version: string;
current?: boolean;
}) {
try {
const path = join(INSTALL_DIR, version);
await remove(path);
const versionPath = join(path, version);
await remove(versionPath);

current && (await remove(join(APPDIR, 'default')));
return;
Expand Down
7 changes: 5 additions & 2 deletions src/renderer/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Themes } from 'types';
type StateType = {
locale: string;
theme: Themes; // from setting
directory: string; // node installation directory
sysTheme: Themes; // system real theme
mirror: string;
messages: I18n.Message;
Expand All @@ -30,7 +31,7 @@ type StateAction = {
};

export default function App() {
const { locale, theme, mirror, localeMessages } =
const { locale, theme, directory, mirror, localeMessages } =
window.Context.getSettingData();

const [state, dispatch] = useReducer(
Expand All @@ -49,6 +50,7 @@ export default function App() {
{
locale,
theme: theme,
directory,
sysTheme: window.Context.getSystemTheme() as Themes,
mirror,
messages: localeMessages,
Expand Down Expand Up @@ -100,7 +102,7 @@ export default function App() {
payload: { ...state, ...setting, messages },
});
},
[state.locale, state.theme, state.mirror],
[state.locale, state.theme, state.directory, state.mirror],
);

const getMessage = useCallback<I18nFn>(
Expand Down Expand Up @@ -177,6 +179,7 @@ export default function App() {
value={{
locale: state.locale,
theme: state.theme,
direction: state.directory,
mirror: state.mirror,
getMessage,
onUpdateSetting,
Expand Down
1 change: 1 addition & 0 deletions src/renderer/appContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Themes } from 'types';
type AppContextType = {
locale: string;
theme: Themes;
direction: string;
mirror: string;
getMessage: I18nFn;
onUpdateSetting: (setting: Nvmd.Setting) => Promise<void>;
Expand Down
Loading

0 comments on commit 87f765e

Please sign in to comment.