Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ AriaNg Native is a desktop application built by [Electron](https://github.com/el
* Play sound after download finished
2. Command line arguments, supporting creating new task by opening file
3. File associations for .torrent/.metalink file
4. Taskbar tray, supporting minimizing to tray
5. Local file system operating support
6. Executing custom command on startup
7. Checking for updates on startup
4. Magnet link protocol handling, supporting opening tasks from browser
5. Taskbar tray, supporting minimizing to tray
6. Local file system operating support
7. Executing custom command on startup
8. Checking for updates on startup

## Introduction of AriaNg
Please visit [https://github.com/mayswind/AriaNg](https://github.com/mayswind/AriaNg) for more information.
Expand Down
7 changes: 7 additions & 0 deletions app/langs/cz_CZ.txt
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,10 @@ stop.name=Automatické vypnutí
stop.description=Zastaví aplikaci po uplynutí SEC sekund. Pokud je zadáno 0, tato funkce je zakázána.
truncate-console-readout.name=Oříznout výstup v konzoli
truncate-console-readout.description=Ořízne výstup do konzole tak, aby se vešel na jeden řádek.
[global]
Copy link
Owner

@mayswind mayswind Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you don't learn a language, please do not submit translation file for it, as inaccurate translations may mislead other users.
You may leave these entries empty in these languages.

Handle magnet links=Obsluhovat magnet odkazy
Open default apps settings=Otevřít nastavení výchozích aplikací
Magnet protocol is enabled but this app is not the default handler. Please update system settings.=Protokol magnet je povolen, ale tato aplikace není výchozí obsluhovač. Aktualizujte nastavení systému.
Is default magnet handler=Výchozí obsluhovač magnet
Yes=Ano
No=Ne
7 changes: 7 additions & 0 deletions app/langs/de_DE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,10 @@ stop.name=Automatische Abschaltzeit
stop.description=Anwendung stoppen, nachdem SEC Sekunden vergangen sind. Bei 0 ist diese Funktion deaktiviert.
truncate-console-readout.name=Konsolenausgabe kürzen
truncate-console-readout.description=Konsolenausgabe kürzen, damit sie in eine Zeile passt.
[global]
Handle magnet links=Magnet-Links verarbeiten
Open default apps settings=Systemeinstellungen für Standard-Apps öffnen
Magnet protocol is enabled but this app is not the default handler. Please update system settings.=Das Magnet-Protokoll ist aktiviert, aber diese App ist nicht der Standard-Handler. Bitte die Systemeinstellungen aktualisieren.
Is default magnet handler=Standard-Magnet-Handler
Yes=Ja
No=Nein
7 changes: 7 additions & 0 deletions app/langs/es.txt
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,10 @@ stop.name=Tiempo de apagado automático
stop.description=Detener la aplicación después de que transcurran 10 segundos. Si se especifica 0, esta función se deshabilita.
truncate-console-readout.name=Truncar la salida de la consola
truncate-console-readout.description=Truncar la lectura de la consola para que quepa en una sola línea.
[global]
Handle magnet links=Gestionar enlaces magnet
Open default apps settings=Abrir la configuración de aplicaciones predeterminadas
Magnet protocol is enabled but this app is not the default handler. Please update system settings.=El protocolo magnet está habilitado, pero esta aplicación no es el manejador predeterminado. Actualiza la configuración del sistema.
Is default magnet handler=Manejador magnet predeterminado
Yes=Sí
No=No
7 changes: 7 additions & 0 deletions app/langs/fr_FR.txt
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,10 @@ stop.name=Temps d'arrêt automatique
stop.description=Arrête l'application au bout de SEC secondes. Si la valeur 0 est donnée, cette fonction est désactivée.
truncate-console-readout.name=Raccourcit la sortie de la console
truncate-console-readout.description=Raccourcit la sortie de la console à une seule ligne.
[global]
Handle magnet links=Gérer les liens magnet
Open default apps settings=Ouvrir les paramètres des applications par défaut
Magnet protocol is enabled but this app is not the default handler. Please update system settings.=Le protocole magnet est activé, mais cette application n'est pas le gestionnaire par défaut. Veuillez mettre à jour les paramètres système.
Is default magnet handler=Gestionnaire magnet par défaut
Yes=Oui
No=Non
7 changes: 7 additions & 0 deletions app/langs/it_IT.txt
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,10 @@ stop.name=Tempo di arresto automatico
stop.description=
truncate-console-readout.name=Tronca l'output della console
truncate-console-readout.description=Tronca l'output della console su una singola riga.
[global]
Handle magnet links=Gestisci link magnet
Open default apps settings=Apri le impostazioni delle app predefinite
Magnet protocol is enabled but this app is not the default handler. Please update system settings.=Il protocollo magnet è abilitato, ma questa app non è il gestore predefinito. Aggiorna le impostazioni di sistema.
Is default magnet handler=Gestore magnet predefinito
Yes=Sì
No=No
7 changes: 7 additions & 0 deletions app/langs/pl_PL.txt
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,10 @@ stop.name=Automatyczne Zakończenie
stop.description=Zakończ działanie programu po upływie SEC sekund. Jeśli 0, ta funkcja jest wyłączona.
truncate-console-readout.name=Ostrzeżenia Konsoli
truncate-console-readout.description=Przytnij wyjście konsoli do jednej linii.
[global]
Handle magnet links=Obsługa linków magnet
Open default apps settings=Otwórz ustawienia domyślnych aplikacji
Magnet protocol is enabled but this app is not the default handler. Please update system settings.=Protokół magnet jest włączony, ale ta aplikacja nie jest domyślnym obsługiwaczem. Zaktualizuj ustawienia systemu.
Is default magnet handler=Domyślny obsługiwacz magnet
Yes=Tak
No=Nie
7 changes: 7 additions & 0 deletions app/langs/ru_RU.txt
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,10 @@ stop.name=Время автоматической остановки
stop.description=Останавливает все активные загрузки и завершает работу aria2.
truncate-console-readout.name=Обрезка вывода консоли
truncate-console-readout.description=Обрезает вывод консоли до одной строки.
[global]
Handle magnet links=Обрабатывать magnet-ссылки
Open default apps settings=Открыть настройки приложений по умолчанию
Magnet protocol is enabled but this app is not the default handler. Please update system settings.=Протокол magnet включён, но это приложение не является обработчиком по умолчанию. Обновите настройки системы.
Is default magnet handler=Обработчик magnet по умолчанию
Yes=Да
No=Нет
7 changes: 7 additions & 0 deletions app/langs/zh_Hans.txt
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,10 @@ stop.name=自动关闭时间
stop.description=在此选项设置的时间(秒)后关闭应用. 如果设置为 0, 此功能将禁用.
truncate-console-readout.name=缩短控制台输出内容
truncate-console-readout.description=缩短控制台输出的内容在一行中.
[global]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file already has a "global" section. You should place newly added entries near the related adjacent entries in the UI similar to what you did in the app/scripts/config/defaultLanguage.js file.

Handle magnet links=处理磁力链接
Open default apps settings=打开系统默认应用设置
Magnet protocol is enabled but this app is not the default handler. Please update system settings.=磁力协议已启用,但当前应用不是默认处理器,请在系统设置中修改。
Is default magnet handler=是否为默认磁力处理器
Yes=是
No=否
7 changes: 7 additions & 0 deletions app/langs/zh_Hant.txt
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,10 @@ stop.name=自動關閉時間
stop.description=在此選項設定的時間(秒)後關閉應用程式. 如果設定為 0, 此功能將停用.
truncate-console-readout.name=縮短控制台輸出內容
truncate-console-readout.description=縮短控制台輸出的內容在一行中.
[global]
Handle magnet links=處理磁力連結
Open default apps settings=開啟系統預設應用程式設定
Magnet protocol is enabled but this app is not the default handler. Please update system settings.=磁力協定已啟用,但目前應用程式不是預設處理器,請到系統設定中修改。
Is default magnet handler=是否為預設磁力處理器
Yes=是
No=否
6 changes: 6 additions & 0 deletions app/scripts/config/defaultLanguage.js
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,12 @@
'Open Browser DevTools': 'Open Browser DevTools',
'Swipe Gesture': 'Swipe Gesture',
'Change Tasks Order by Drag-and-drop': 'Change Tasks Order by Drag-and-drop',
'Handle magnet links': 'Handle magnet links',
'Is default magnet handler': 'Is default magnet handler',
'Yes': 'Yes',
'No': 'No',
'Magnet protocol is enabled but this app is not the default handler. Please update system settings.': 'Magnet protocol is enabled but this app is not the default handler. Please update system settings.',
'Open default apps settings': 'Open default apps settings',
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The above entries are missing:
"Default magnet app"
"This feature is not supported on your system."
"Failed to open system settings."

'Action After Creating New Tasks': 'Action After Creating New Tasks',
'Navigate to Task List Page': 'Navigate to Task List Page',
'Navigate to Task Detail Page': 'Navigate to Task Detail Page',
Expand Down
34 changes: 34 additions & 0 deletions app/scripts/controllers/settings-ariang.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
config.execCommandOptionsOnStartup = 'as-detached-process';
}

config.enableMagnetProtocol = originalConfig.enableMagnetProtocol !== false;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

config.enableMagnetProtocol = !!originalConfig.enableMagnetProtocol


return config;
};

Expand All @@ -70,6 +72,7 @@
importNativeSetting(settings, 'execCommandOnStartup', $scope.setExecCommandOnStartup);
importNativeSetting(settings, 'execCommandArgumentsOnStartup', $scope.setExecCommandArgumentsOnStartup);
importNativeSetting(settings, 'execCommandOptionsOnStartup', $scope.setExecCommandOptionsOnStartup);
importNativeSetting(settings, 'enableMagnetProtocol', $scope.setEnableMagnetProtocol);
ariaNgSettingService.importAllOptions(settings);
};

Expand Down Expand Up @@ -149,6 +152,7 @@
isSupportReconnect: aria2SettingService.canReconnect(),
isSupportBlob: ariaNgFileService.isSupportBlob(),
isSupportDarkMode: ariaNgSettingService.isBrowserSupportDarkMode(),
magnetProtocolStatus: null,
importSettings: null,
exportSettings: null,
exportSettingsCopied: false,
Expand Down Expand Up @@ -439,6 +443,36 @@
}
};

$scope.setEnableMagnetProtocol = function (value) {
var status = ariaNgNativeElectronService.setEnableMagnetProtocol(value);

if (status) {
$scope.context.magnetProtocolStatus = status;
}

if (value && status && !status.isDefault) {
ariaNgCommonService.showInfo('Default magnet app', 'Magnet protocol is enabled but this app is not the default handler. Please update system settings.');
}
};

$scope.openSystemDefaultAppsSetting = function () {
ariaNgNativeElectronService.openSystemDefaultAppsSetting().then(function (success) {
if (!success) {
ariaNgCommonService.showError('This feature is not supported on your system.');
}
}).catch(function () {
ariaNgCommonService.showError('Failed to open system settings.');
});
};

ariaNgNativeElectronService.getMagnetProtocolStatusAsync().then(function (status) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The promise returned by ariaNgNativeElectronService.getMagnetProtocolStatusAsync() can be combined with the default loadingPromise (L649) using $q.all. This provides a better user experience by ensuring that this status is fully loaded when the user opens the interface.

Image

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition, the surrounding code in this area is all assigning values to $scope, so this code should be placed at the end of the file, together with the loadingPromise logic.

if (!status) {
return;
}

$scope.context.magnetProtocolStatus = status;
});

$scope.browseAndSetExecCommandOnStartup = function () {
ariaNgNativeElectronService.showOpenFileDialogAsync([{
name: ariaNgLocalizationService.getLocalizedText('All Files'),
Expand Down
9 changes: 9 additions & 0 deletions app/scripts/services/ariaNgNativeElectronService.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,15 @@
setExecDetachedCommandOnStartup: function (value) {
invokeMainProcessMethod('render-set-native-config-exec-detached-command-on-startup', value);
},
setEnableMagnetProtocol: function (value) {
return invokeMainProcessMethodSync('render-set-native-config-enable-magnet-protocol', value);
},
getMagnetProtocolStatusAsync: function () {
return invokeMainProcessMethodAsync('render-get-native-config-magnet-protocol-status');
},
openSystemDefaultAppsSetting: function () {
return invokeMainProcessMethodAsync('render-open-system-default-apps-setting');
},
getLastCheckUpdatesTimeAsync: function (callback) {
return invokeMainProcessMethodAsync('render-get-native-config-last-check-updates-time')
.then(function onReceive(lastCheckUpdatesTime) {
Expand Down
29 changes: 29 additions & 0 deletions app/views/settings-ariang.html
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,35 @@
</select>
</div>
</div>
<div class="row">
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this option should be placed after "Default Window Position", as that better aligns with typical user expectations.

<div class="setting-key setting-key-without-desc col-sm-4">
<span translate>Handle magnet links</span>
</div>
<div class="setting-value col-sm-8">
<div class="input-group" ng-if="context.magnetProtocolStatus">
<select class="form-control" ng-model="context.nativeSettings.enableMagnetProtocol"
ng-change="setEnableMagnetProtocol(context.nativeSettings.enableMagnetProtocol)"
ng-options="option.value as (option.name | translate) for option in context.trueFalseOptions">
</select>
<span class="input-group-addon">
<span translate>Is default magnet handler</span>:
<span ng-if="context.magnetProtocolStatus.isDefault" translate>Yes</span>
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would using bootstrap label here provide a better user experience?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I suggest placing the "Yes" and "No" entries earlier in the language file, for example near "Enabled" and "Disabled".

<span ng-if="!context.magnetProtocolStatus.isDefault" translate>No</span>
</span>
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-click="openSystemDefaultAppsSetting()"
ng-disabled="!context.nativeSettings.enableMagnetProtocol || context.magnetProtocolStatus.isDefault">
<span translate>Open default apps settings</span>
</button>
</span>
</div>
<select class="form-control" style="width: 100%;" ng-if="!context.magnetProtocolStatus"
ng-model="context.nativeSettings.enableMagnetProtocol"
ng-change="setEnableMagnetProtocol(context.nativeSettings.enableMagnetProtocol)"
ng-options="option.value as (option.name | translate) for option in context.trueFalseOptions">
</select>
</div>
</div>
<div class="row">
<div class="setting-key setting-key-without-desc col-sm-4">
<span translate>RPC List Display Order</span>
Expand Down
4 changes: 4 additions & 0 deletions main/config/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ const userSettingsSchema = {
execDetachedCommandOnStartup: {
type: 'boolean'
},
enableMagnetProtocol: {
type: 'boolean'
},
lastCheckUpdatesTime: {
type: 'number'
}
Expand All @@ -54,6 +57,7 @@ let config = {
execCommandOnStartup: userSettingsStore.get('execCommandOnStartup'),
execCommandArgumentsOnStartup: userSettingsStore.get('execCommandArgumentsOnStartup'),
execDetachedCommandOnStartup: userSettingsStore.get('execDetachedCommandOnStartup', false),
enableMagnetProtocol: userSettingsStore.get('enableMagnetProtocol', true),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest using false as the default to keep the behavior consistent with previous versions.

lastCheckUpdatesTime: userSettingsStore.get('lastCheckUpdatesTime') || 0,
save: function (item) {
if (item && this[item] !== undefined) {
Expand Down
86 changes: 85 additions & 1 deletion main/ipc/main-process.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict';

const path = require('path');
const electron = require('electron');

const core = require('../core');
Expand All @@ -14,10 +15,55 @@ const localfs = require('../lib/localfs');
const bittorrent = require('../lib/bittorrent');

const shell = electron.shell;
const app = electron.app;
const nativeTheme = electron.nativeTheme;
const dialog = electron.dialog;
const ipcMain = electron.ipcMain;

let setMagnetProtocolEnabled = function (enabled) {
try {
if (enabled) {
if (app.isPackaged) {
return app.setAsDefaultProtocolClient('magnet');
}

if (process.defaultApp && process.argv.length > 1) {
return app.setAsDefaultProtocolClient('magnet', process.execPath, [path.resolve(process.argv[1])]);
}

return app.setAsDefaultProtocolClient('magnet');
}

if (app.isPackaged) {
return app.removeAsDefaultProtocolClient('magnet');
}

if (process.defaultApp && process.argv.length > 1) {
return app.removeAsDefaultProtocolClient('magnet', process.execPath, [path.resolve(process.argv[1])]);
}

return app.removeAsDefaultProtocolClient('magnet');
} catch (ex) {
return false;
}
};

let isDefaultMagnetProtocol = function () {
try {
if (app.isPackaged) {
return app.isDefaultProtocolClient('magnet');
}

if (process.defaultApp && process.argv.length > 1) {
return app.isDefaultProtocolClient('magnet', process.execPath, [path.resolve(process.argv[1])]);
}

return app.isDefaultProtocolClient('magnet');
} catch (ex) {
return false;
}
};

ipcMain.on('render-sync-get-runtime-environment', (event) => {
if (!process || !process.versions) {
return null;
Expand Down Expand Up @@ -116,7 +162,8 @@ ipcMain.on('render-sync-get-native-config', (event) => {
minimizedToTray: config.minimizedToTray,
execCommandOnStartup: config.execCommandOnStartup,
execCommandArgumentsOnStartup: config.execCommandArgumentsOnStartup,
execDetachedCommandOnStartup: config.execDetachedCommandOnStartup
execDetachedCommandOnStartup: config.execDetachedCommandOnStartup,
enableMagnetProtocol: config.enableMagnetProtocol
};
});

Expand Down Expand Up @@ -145,6 +192,25 @@ ipcMain.on('render-set-native-config-exec-detached-command-on-startup', (event,
config.save('execDetachedCommandOnStartup');
});

ipcMain.on('render-set-native-config-enable-magnet-protocol', (event, value) => {
config.enableMagnetProtocol = !!value;
config.save('enableMagnetProtocol');
const registered = setMagnetProtocolEnabled(config.enableMagnetProtocol);

event.returnValue = {
enabled: config.enableMagnetProtocol,
isDefault: isDefaultMagnetProtocol(),
registered: registered
};
});

ipcMain.handle('render-get-native-config-magnet-protocol-status', () => {
return {
enabled: !!config.enableMagnetProtocol,
isDefault: isDefaultMagnetProtocol()
};
});

ipcMain.handle('render-get-native-config-last-check-updates-time', (event) => {
return config.lastCheckUpdatesTime;
});
Expand Down Expand Up @@ -225,6 +291,24 @@ ipcMain.on('render-open-external-url', (event, url) => {
shell.openExternal(url);
});

ipcMain.handle('render-open-system-default-apps-setting', async () => {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This project does not use the async / await keywords consistently.

try {
if (process.platform === 'win32') {
await shell.openExternal('ms-settings:defaultapps');
return true;
}

if (process.platform === 'darwin') {
await shell.openExternal('x-apple.systempreferences:com.apple.preference.general');
return true;
}

return false;
} catch (ex) {
return false;
}
});

ipcMain.on('render-sync-get-package-file-content', (event, path) => {
event.returnValue = localfs.readPackageFile(path);
});
Expand Down
Loading