mirror of
https://github.com/iNavFlight/inav-configurator.git
synced 2025-07-12 19:10:21 +03:00
Fixes, Readme, Makers
This commit is contained in:
parent
6fe68a6b73
commit
0d1502e03d
28 changed files with 1055 additions and 408 deletions
34
README.md
34
README.md
|
@ -25,25 +25,25 @@ Depending on the target operating system, _INAV Configurator_ is distributed as
|
|||
### Windows
|
||||
|
||||
1. Visit [release page](https://github.com/iNavFlight/inav-configurator/releases)
|
||||
1. Download Configurator for Windows platform (win32 or win64 is present)
|
||||
1. Extract ZIP archive
|
||||
1. Run the INAV Configurator app from the unpacked folder
|
||||
1. Configurator is not signed, so you have to allow Windows to run untrusted applications. There might be a monit for it during the first run
|
||||
2. Download Configurator for Windows platform (win32 or win64 is present)
|
||||
3. Install
|
||||
* Extract ZIP archive and run the INAV Configurator app from the unpacked folder
|
||||
* OR just use the setup program `INAV Configurator.msi`
|
||||
|
||||
4. Configurator is not signed, so you have to allow Windows to run untrusted applications. There might be a monit for it during the first run
|
||||
|
||||
### Linux
|
||||
|
||||
### Outdated, TODO: Update for Electron
|
||||
|
||||
1. Visit [release page](https://github.com/iNavFlight/inav-configurator/releases)
|
||||
2. Download Configurator for Linux platform (linux32 and linux64 are present)
|
||||
* **.rpm** is the Fedora installation file. Just download and install using `sudo dnf localinstall /path/to/INAV-Configurator_linux64-x.y.z-x86_64.rpm` or open it with a package manager (e.g. via Files)
|
||||
* **.deb** is the Debian/Ubuntu installation file. Just download and install using `sudo apt install /path/to/INAV-Configurator_linux64_x.y.z.deb` or open it with a package manager (e.g. via the File Manager)
|
||||
* **.tar.gz** is a universal archive. Download and continue with these instructions to install
|
||||
3. Change to the directory containing the downloaded **tar.gz** file
|
||||
* **.zip** is a universal archive. Download and continue with these instructions to install
|
||||
3. Change to the directory containing the downloaded **zip** file
|
||||
4. download [this](https://raw.githubusercontent.com/iNavFlight/inav-configurator/master/assets/linux/inav-configurator.desktop) file to the same directory. Its filename should be `inav-configurator.desktop`.
|
||||
5. Extract **tar.gz** archive
|
||||
5. Extract **zip** archive
|
||||
```
|
||||
tar -C /tmp/ -xf INAV-Configurator_linuxNN_x.y.z.tar.gz
|
||||
unzip INAV-Configurator_linuxNN_x.y.z.tar.gz -d /tmp/
|
||||
```
|
||||
**NN** is the bits of your OS. **x.y.z** is the INAV Configurator version number.
|
||||
|
||||
|
@ -72,9 +72,10 @@ sudo mv inav-configurator.desktop /usr/share/applications/
|
|||
### Mac
|
||||
|
||||
1. Visit [release page](https://github.com/iNavFlight/inav-configurator/releases)
|
||||
1. Download Configurator for the Mac platform
|
||||
1. Extract ZIP archive
|
||||
1. Run INAV Configurator
|
||||
2. Download Configurator for the Mac platform
|
||||
3. Install
|
||||
* Extract ZIP archive and run INAV Configurator
|
||||
* OR use the DMG package for installation
|
||||
|
||||
## Building and running INAV Configurator locally (for development)
|
||||
|
||||
|
@ -92,6 +93,13 @@ Options:
|
|||
|
||||
See [Electron Forge CLI Documentation](https://www.electronforge.io/cli#options-2) for details
|
||||
|
||||
To build the setup program for windows, you have to install [WiX Toolset V3](https://github.com/wixtoolset/wix3/releases) and add the `bin` folder to you `PATH`, e.g.
|
||||
```C:\Program Files (x86)\WiX Toolset v3.14\bin```
|
||||
|
||||
To build deb and rpm packages for Linux, you have to install the following packages:
|
||||
- Ubuntu/Debian: `dpkg, fakeroot, rpmbuild, build-essential, libudev-dev`
|
||||
- OpenSuse/Fedora: `dpkg, fakeroot, rpmbuild, systemd-devel, devel-basis (zypper install -t pattern devel_basis), zip`
|
||||
|
||||
Example (note the double -- ):
|
||||
``` npm run make -- --arch="x64" ```
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
Name=INAV Configurator
|
||||
Comment=Crossplatform configuration tool for the INAV flight control system
|
||||
Exec=/opt/inav/inav-configurator/inav-configurator
|
||||
Icon=/opt/inav/inav-configurator/icon/inav_icon_128.png
|
||||
Icon=/opt/inav/inav-configurator/resources/app/assets/linux/icon/inav_icon_128.png
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Utility
|
BIN
assets/windows/background.jpg
Normal file
BIN
assets/windows/background.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
BIN
assets/windows/banner.jpg
Normal file
BIN
assets/windows/banner.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 151 KiB |
Binary file not shown.
Before Width: | Height: | Size: 32 KiB |
|
@ -1,169 +0,0 @@
|
|||
; ------------------------------------------
|
||||
; Installer for INAV
|
||||
; ------------------------------------------
|
||||
; It receives from the command line with /D the parameters:
|
||||
; version
|
||||
; archName
|
||||
; archAllowed
|
||||
; archInstallIn64bit
|
||||
; sourceFolder
|
||||
; targetFolder
|
||||
|
||||
#define ApplicationName "INAV Configurator"
|
||||
#define CompanyName "The INAV open source project"
|
||||
#define CompanyUrl "https://github.com/iNavFlight/inav"
|
||||
#define ExecutableFileName "inav-configurator.exe"
|
||||
#define GroupName "INAV"
|
||||
#define InstallerFileName "INAV-Configurator_" + archName + "_" + version
|
||||
#define SourcePath "..\..\" + sourceFolder + "\inav-configurator\" + archName
|
||||
#define TargetFolderName "INAV-Configurator"
|
||||
#define UpdatesUrl "https://github.com/iNavFlight/inav-configurator/releases"
|
||||
|
||||
[CustomMessages]
|
||||
AppName=inav-configurator
|
||||
LaunchProgram=Start {#ApplicationName}
|
||||
|
||||
[Files]
|
||||
Source: "{#SourcePath}\*"; DestDir: "{app}"; Flags: recursesubdirs
|
||||
|
||||
[Icons]
|
||||
; Programs group
|
||||
Name: "{group}\{#ApplicationName}"; Filename: "{app}\{#ExecutableFileName}";
|
||||
; Desktop icon
|
||||
Name: "{autodesktop}\{#ApplicationName}"; Filename: "{app}\{#ExecutableFileName}";
|
||||
; Non admin users, uninstall icon
|
||||
Name: "{group}\Uninstall {#ApplicationName}"; Filename: "{uninstallexe}"; Check: not IsAdminInstallMode
|
||||
|
||||
[Languages]
|
||||
; English default, it must be first
|
||||
Name: "en"; MessagesFile: "compiler:Default.isl"
|
||||
; Official languages
|
||||
;Name: "ca"; MessagesFile: "compiler:Languages\Catalan.isl"
|
||||
;Name: "da"; MessagesFile: "compiler:Languages\Danish.isl"
|
||||
;Name: "de"; MessagesFile: "compiler:Languages\German.isl"
|
||||
;Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl"
|
||||
;Name: "fr"; MessagesFile: "compiler:Languages\French.isl"
|
||||
;Name: "it"; MessagesFile: "compiler:Languages\Italian.isl"
|
||||
;Name: "ja"; MessagesFile: "compiler:Languages\Japanese.isl"
|
||||
;Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl"
|
||||
;Name: "pt"; MessagesFile: "compiler:Languages\Portuguese.isl"
|
||||
;Name: "pl"; MessagesFile: "compiler:Languages\Polish.isl"
|
||||
;Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl"
|
||||
; Not official. Sometimes not updated to latest version (strings missing)
|
||||
;Name: "ga"; MessagesFile: "unofficial_inno_languages\Galician.isl"
|
||||
;Name: "eu"; MessagesFile: "unofficial_inno_languages\Basque.isl"
|
||||
;Name: "hr"; MessagesFile: "unofficial_inno_languages\Croatian.isl"
|
||||
;Name: "hu"; MessagesFile: "unofficial_inno_languages\Hungarian.isl"
|
||||
;Name: "id"; MessagesFile: "unofficial_inno_languages\Indonesian.isl"
|
||||
;Name: "ko"; MessagesFile: "unofficial_inno_languages\Korean.isl"
|
||||
;Name: "lv"; MessagesFile: "unofficial_inno_languages\Latvian.isl"
|
||||
;Name: "sv"; MessagesFile: "unofficial_inno_languages\Swedish.isl"
|
||||
;Name: "zh_CN"; MessagesFile: "unofficial_inno_languages\ChineseSimplified.isl"
|
||||
;Name: "zh_TW"; MessagesFile: "unofficial_inno_languages\ChineseTraditional.isl"
|
||||
; Not available
|
||||
; pt_BR (Portuguese Brasileiro)
|
||||
|
||||
[Run]
|
||||
; Add a checkbox to start the app after installed
|
||||
Filename: {app}\{cm:AppName}.exe; Description: {cm:LaunchProgram,{cm:AppName}}; Flags: nowait postinstall skipifsilent
|
||||
|
||||
[Setup]
|
||||
AppId=2e5662ca-1fb3-8f1e-a7e1-e390add7a19d
|
||||
AppName={#ApplicationName}
|
||||
AppPublisher={#CompanyName}
|
||||
AppPublisherURL={#CompanyUrl}
|
||||
AppUpdatesURL={#UpdatesUrl}
|
||||
AppVersion={#version}
|
||||
ArchitecturesAllowed={#archAllowed}
|
||||
ArchitecturesInstallIn64BitMode={#archInstallIn64bit}
|
||||
Compression=lzma2
|
||||
DefaultDirName={autopf}\{#GroupName}\{#TargetFolderName}
|
||||
DefaultGroupName={#GroupName}\{#ApplicationName}
|
||||
LicenseFile=..\..\LICENSE
|
||||
MinVersion=6.2
|
||||
OutputBaseFilename={#InstallerFileName}
|
||||
OutputDir=..\..\{#targetFolder}\
|
||||
PrivilegesRequiredOverridesAllowed=commandline dialog
|
||||
SetupIconFile=inav_installer_icon.ico
|
||||
ShowLanguageDialog=yes
|
||||
SolidCompression=yes
|
||||
UninstallDisplayIcon={app}\{#ExecutableFileName}
|
||||
UninstallDisplayName={#ApplicationName}
|
||||
WizardImageFile=inav_installer.bmp
|
||||
WizardSmallImageFile=inav_installer_small.bmp
|
||||
WizardStyle=modern
|
||||
|
||||
[Code]
|
||||
function GetOldNsisUninstallerPath(): String;
|
||||
var
|
||||
RegKey: String;
|
||||
begin
|
||||
Result := '';
|
||||
// Look into the different registry entries: win32, win64 and without user rights
|
||||
if not RegQueryStringValue(HKLM, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\INAV Configurator', 'UninstallString', Result) then
|
||||
begin
|
||||
if not RegQueryStringValue(HKLM, 'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\INAV Configurator', 'UninstallString', Result) then
|
||||
begin
|
||||
RegQueryStringValue(HKCU, 'SOFTWARE\INAV\INAV Configurator', 'UninstallString', Result)
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetQuietUninstallerPath(): String;
|
||||
var
|
||||
RegKey: String;
|
||||
begin
|
||||
Result := '';
|
||||
RegKey := Format('%s\%s_is1', ['Software\Microsoft\Windows\CurrentVersion\Uninstall', '{#emit SetupSetting("AppId")}']);
|
||||
if not RegQueryStringValue(HKEY_LOCAL_MACHINE, RegKey, 'QuietUninstallString', Result) then
|
||||
begin
|
||||
RegQueryStringValue(HKEY_CURRENT_USER, RegKey, 'QuietUninstallString', Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
function InitializeSetup(): Boolean;
|
||||
var
|
||||
ResultCode: Integer;
|
||||
ParameterStr : String;
|
||||
UninstPath : String;
|
||||
begin
|
||||
|
||||
Result := True;
|
||||
|
||||
// Check if the application is already installed by the old NSIS installer, and uninstall it
|
||||
UninstPath := GetOldNsisUninstallerPath();
|
||||
|
||||
// Found, start uninstall
|
||||
if UninstPath <> '' then
|
||||
begin
|
||||
|
||||
UninstPath := RemoveQuotes(UninstPath);
|
||||
|
||||
// Add this parameter to not return until uninstall finished. The drawback is that the uninstaller file is not deleted
|
||||
ParameterStr := '_?=' + ExtractFilePath(UninstPath);
|
||||
|
||||
if Exec(UninstPath, ParameterStr, '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
|
||||
begin
|
||||
// Delete the unistaller file and empty folders. Not deleting the files.
|
||||
DeleteFile(UninstPath);
|
||||
DelTree(ExtractFilePath(UninstPath), True, False, True);
|
||||
end
|
||||
else begin
|
||||
Result := False;
|
||||
MsgBox('Error uninstalling old Configurator ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
|
||||
// Search for new Inno Setup installations
|
||||
UninstPath := GetQuietUninstallerPath();
|
||||
if UninstPath <> '' then
|
||||
begin
|
||||
if not Exec('>', UninstPath, '', SW_SHOW, ewWaitUntilTerminated, ResultCode) then
|
||||
begin
|
||||
Result := False;
|
||||
MsgBox('Error uninstalling Configurator ' + SysErrorMessage(ResultCode) + '.', mbError, MB_OK);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
162
assets/windows/wix.xml
Normal file
162
assets/windows/wix.xml
Normal file
|
@ -0,0 +1,162 @@
|
|||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
|
||||
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
|
||||
<!-- http://wixtoolset.org/documentation/manual/v3/xsd/wix/product.html -->
|
||||
<Product Id="{{ProductCode}}"
|
||||
UpgradeCode="{{UpgradeCode}}"
|
||||
Name = "{{ApplicationName}}"
|
||||
Version="{{Version}}"
|
||||
Manufacturer="{{Manufacturer}}"
|
||||
Language="{{Language}}">
|
||||
<!-- Only run this installer on Windows 7 or up (or if it"s already installed, I guess) -->
|
||||
<!-- <Condition Message="This application is only supported on Windows 7 or higher.">
|
||||
<![CDATA[Installed OR (VersionNT >= 601)]]>
|
||||
</Condition> -->
|
||||
<!-- http://wixtoolset.org/documentation/manual/v3/xsd/wix/package.html -->
|
||||
<Package InstallerVersion="405"
|
||||
Compressed="yes"
|
||||
Comments="Windows Installer Package"
|
||||
Platform="{{Platform}}"
|
||||
InstallScope="{{PackageScope}}"/>
|
||||
<!-- Don't allow downgrades -->
|
||||
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A later version of this product is already installed. Setup will now exit."/>
|
||||
<!-- This will hide our Uninstall entry in Apps & Features. We doing this so
|
||||
we can write our own which we can better control. -->
|
||||
<Property Id="ARPSYSTEMCOMPONENT" Value="1" />
|
||||
<!-- While the MSI package is hidden in Apps & Features, it can still be queried
|
||||
via PowerShell and other means. To differentiate we give the public entry a slightly
|
||||
different name to make admins life easier. -->
|
||||
<Property Id="VisibleProductName" Value="{{ApplicationName}}" />
|
||||
<!-- Tells the package to install perUser or perMachine. In case of perUser, all
|
||||
files will be redirected to the user profile and all registry entries to HKCU. -->
|
||||
<Property Id="MSIINSTALLPERUSER" Secure="yes" Value="{{InstallPerUser}}" />
|
||||
<!-- Overides the default install mode. It solves a problem where
|
||||
individual packaged files that have the same version as in previous
|
||||
installed App version will be deleted if the files are in use during
|
||||
this upgrade. Unfortunately this causes an ICE 40 warning during linking. -->
|
||||
<Property Id="REINSTALLMODE" Value="emus" />
|
||||
<!-- Overrides the default reboot behavior if files are in use during the upgrade.
|
||||
By default, this will be set to "ReallySuppress" to make sure no unexpected reboot will happpen.-->
|
||||
<Property Id="REBOOT" Value="{{RebootMode}}" />
|
||||
<!-- Installlation level to use that determines which features are installed.
|
||||
see guides/enduser.md to check which Install Level maps to which feature that will
|
||||
correspondingly get installed.
|
||||
If not set, this will default to "2" (Main Feature, Launch On Login) -->
|
||||
<Property Id="INSTALLLEVEL" Value="{{InstallLevel}}" />
|
||||
<!-- Allows to customize the Windows user group that gets access rights on
|
||||
the install folder in cas the auto-updater is installed. User that run the App
|
||||
must be part of that user group to be able to auto-update. -->
|
||||
<Property Id="UPDATERUSERGROUP" Value="Users" />
|
||||
<!-- A property to define whether the auto-updater is enabled when the
|
||||
feature gets installed. This way the update can be installed but also be disabled
|
||||
by overwriting the default value. -->
|
||||
<Property Id="AUTOUPDATEENABLED" Value="1" />
|
||||
<!-- Necessary registry search to find the install path which is used by the
|
||||
PurgeOnUninstall action. Since this package can be installed perUser or perMachine,
|
||||
we have to look in both places. First successful search wins. -->
|
||||
<Property Id="INSTALLPATH">
|
||||
<RegistrySearch Key="SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{{{ProductCode}}}.msq"
|
||||
Root="HKCU"
|
||||
Type="raw"
|
||||
Id="INSTALLPATH_REGSEARCH_HKCU"
|
||||
Name="InstallPath"
|
||||
Win64="{{Win64YesNo}}"/>
|
||||
<RegistrySearch Key="SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{{{ProductCode}}}.msq"
|
||||
Root="HKLM"
|
||||
Type="raw"
|
||||
Id="INSTALLPATH_REGSEARCH_HKLM"
|
||||
Name="InstallPath"
|
||||
Win64="{{Win64YesNo}}"/>
|
||||
</Property>
|
||||
<!-- Lets change the product name depending on the perUser installMode.
|
||||
This way the user and admins can see in which scope the MSI was installed. -->
|
||||
<SetProperty Action="SetVisibleProductName" Id="VisibleProductName" Sequence="both" Before="AppSearch" Value="{{ApplicationName}} (User)">
|
||||
<![CDATA[MSIINSTALLPERUSER = "1"]]>
|
||||
</SetProperty>
|
||||
<!-- Again we give thee MSI generaten entry a slightly different name to help
|
||||
differentiate between the public one and the invisible one. -->
|
||||
<SetProperty Action="SetProductName" Id="ProductName" Sequence="both" Before="AppSearch" Value="{{ApplicationName}} (User - MSI)">
|
||||
<![CDATA[MSIINSTALLPERUSER = "1"]]>
|
||||
</SetProperty>
|
||||
|
||||
<Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>
|
||||
<!-- {{Icon}}-->
|
||||
<!-- {{UI}} -->
|
||||
|
||||
<!-- Step 2: Add files and directories -->
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<!-- Installation files to %PROGRAMFILES% -->
|
||||
<Directory Id="{{ProgramFilesFolder}}">
|
||||
<!-- {{Directories}} -->
|
||||
</Directory>
|
||||
|
||||
<!-- Desktop -->
|
||||
<Directory Id="DesktopFolder" Name="Desktop" />
|
||||
|
||||
<!-- Start Menu -->
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="{{ShortcutFolderName}}"/>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<!-- Step 3: Add app to Start Menu -->
|
||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
||||
<Component Id="ApplicationShortcut" Guid="{{ApplicationShortcutGuid}}" Win64="{{Win64YesNo}}">
|
||||
<Shortcut Id="ApplicationStartMenuShortcut"
|
||||
Name="{{ShortcutName}}"
|
||||
Description="{{ApplicationDescription}}"
|
||||
Target="[APPLICATIONROOTDIRECTORY]{{ApplicationBinary}}.exe"
|
||||
WorkingDirectory="APPLICATIONROOTDIRECTORY">
|
||||
<!-- {{ShortcutProperties}} -->
|
||||
</Shortcut>
|
||||
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
|
||||
<RegistryValue Root="HKCU"
|
||||
Key="Software\Microsoft\{{ApplicationShortName}}"
|
||||
Name="installed"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes"/>
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- Step 4: Add app desktop shortcut -->
|
||||
<DirectoryRef Id="DesktopFolder">
|
||||
<Component Id="DesktopShortcut" Guid="{{DesktopShortcutGuid}}" >
|
||||
<Shortcut Id="MyDesktopShortcut"
|
||||
Name="{{ShortcutName}}"
|
||||
Description="{{ApplicationDescription}}"
|
||||
Target="[APPLICATIONROOTDIRECTORY]{{ApplicationBinary}}.exe"
|
||||
WorkingDirectory="APPLICATIONROOTDIRECTORY"/>
|
||||
<RegistryValue Root="HKCU"
|
||||
Key="Software\Microsoft\{{ApplicationShortName}}"
|
||||
Name="installed"
|
||||
Type="integer"
|
||||
Value="1"
|
||||
KeyPath="yes" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- {{AutoUpdatePermissions}} -->
|
||||
|
||||
<!-- Lets cleanup any files that are were not part of the initial install
|
||||
via this MSI. Such as newer versions installed by the auto-updater. -->
|
||||
<DirectoryRef Id="APPLICATIONROOTDIRECTORY">
|
||||
<Component Id="PurgeOnUninstall" Guid="{{RandomGuid}}" Win64="{{Win64YesNo}}">
|
||||
<CreateFolder/>
|
||||
<util:RemoveFolderEx On="uninstall" Property="INSTALLPATH" />
|
||||
</Component>
|
||||
</DirectoryRef>
|
||||
|
||||
<Feature Id="Complete" Title="{{ApplicationName}} ({{SemanticVersion}})" Description="The complete package." Display="expand" Level="1" {{ConfigurableDirectory}}>
|
||||
<!-- Step 5: Tell WiX to install the files -->
|
||||
<Feature Id="MainApplication" Title="Main Application" Level="1" Description="The main components to run the applications." >
|
||||
<!-- {{ComponentRefs}} -->
|
||||
<ComponentRef Id="ApplicationShortcut" />
|
||||
<ComponentRef Id="DesktopShortcut" />
|
||||
<ComponentRef Id="PurgeOnUninstall" />
|
||||
</Feature>
|
||||
<!-- {{AutoLaunchFeature}} -->
|
||||
<!-- {{AutoUpdateFeature}} -->
|
||||
</Feature>
|
||||
<!-- {{AutoRun}} -->
|
||||
</Product>
|
||||
</Wix>
|
|
@ -1,27 +1,81 @@
|
|||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
module.exports = {
|
||||
packagerConfig: {
|
||||
executableName: "inav-configurator",
|
||||
asar: false,
|
||||
icon: 'images/inav'
|
||||
icon: 'images/inav',
|
||||
ignore: [
|
||||
"^(\/\.vscode$)",
|
||||
"^(\/support$)",
|
||||
".gitattributes",
|
||||
".gitignore",
|
||||
"3D_model_creation.md",
|
||||
"LICENSE",
|
||||
"MAPPROXY.md",
|
||||
"package-lock.json",
|
||||
"README.md",
|
||||
"inav_icon_128.psd",
|
||||
]
|
||||
},
|
||||
rebuildConfig: {},
|
||||
makers: [
|
||||
{
|
||||
name: '@electron-forge/maker-squirrel',
|
||||
name: '@electron-forge/maker-wix',
|
||||
config: {
|
||||
iconUrl: "https://raw.githubusercontent.com/iNavFlight/inav-configurator/master/images/inav.ico",
|
||||
loadingGif: "images/inav-installing.gif"
|
||||
name: "INAV Configurator",
|
||||
shortName: "INAV",
|
||||
description: "Configurator for the open source flight controller software INAV.",
|
||||
programFilesFolderName: "inav-configurator",
|
||||
shortcutFolderName: "INAV",
|
||||
manufacturer: "The INAV open source project",
|
||||
appUserModelId: "com.inav.configurator",
|
||||
icon: path.join(__dirname, "./assets/windows/inav_installer_icon.ico"),
|
||||
upgradeCode: "13606ff3-b0bc-4dde-8fac-805bc8aed2f8",
|
||||
ui : {
|
||||
enabled: false,
|
||||
chooseDirectory: true,
|
||||
images: {
|
||||
background: path.join(__dirname, "./assets/windows/background.jpg"),
|
||||
banner: path.join(__dirname, "./assets/windows/banner.jpg")
|
||||
}
|
||||
},
|
||||
beforeCreate: (msiCreator) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fs.readFile(path.join(__dirname,"./assets/windows/wix.xml"), "utf8" , (err, content) => {
|
||||
if (err) {
|
||||
reject (err);
|
||||
}
|
||||
msiCreator.wixTemplate = content;
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: '@electron-forge/maker-dmg',
|
||||
config: {
|
||||
name: "INAV Configurator",
|
||||
background: "./assets/osx/dmg-background.png"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: '@electron-forge/maker-zip',
|
||||
platforms: ['win32', 'darwin'],
|
||||
platforms: ['win32', 'linux', 'darwin'],
|
||||
},
|
||||
{
|
||||
name: '@electron-forge/maker-deb',
|
||||
config: {
|
||||
options: {
|
||||
icon: "images/inav_icon_128.png"
|
||||
name: "inav-configurator",
|
||||
productName: "INAV Configurator",
|
||||
categories: ["Utility"],
|
||||
icon: "./assets/linux/icon/inav_icon_128.png",
|
||||
description: "Configurator for the open source flight controller software INAV.",
|
||||
homepage: "https://github.com/inavflight/",
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
|
@ -29,7 +83,13 @@ module.exports = {
|
|||
name: '@electron-forge/maker-rpm',
|
||||
config: {
|
||||
options: {
|
||||
icon: "images/inav_icon_128.png"
|
||||
name: "inav-configurator",
|
||||
productName: "INAV Configurator",
|
||||
license: "GPL-3.0",
|
||||
categories: ["Utility"],
|
||||
icon: "./assets/linux/icon/inav_icon_128.png",
|
||||
description: "Configurator for the open source flight controller software INAV.",
|
||||
homepage: "https://github.com/inavflight/",
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
const semver = require('semver');
|
||||
|
||||
const { GUI } = require('./gui');
|
||||
const jBox = require('./libraries/jBox/jBox.min.js');
|
||||
const jBox = require('./libraries/jBox/jBox.min');
|
||||
const i18n = require('./localization');
|
||||
|
||||
var appUpdater = appUpdater || {};
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
window.$ = window.jQuery = require('jquery'),
|
||||
require('jquery-ui-dist/jquery-ui'),
|
||||
require('jquery-textcomplete'),
|
||||
require('./libraries/jquery.flightindicators.js'),
|
||||
require('./libraries/jquery.nouislider.all.min.js'),
|
||||
require('./libraries/jquery.ba-throttle-debounce.js');
|
||||
require('./libraries/jquery.flightindicators'),
|
||||
require('./libraries/jquery.nouislider.all.min'),
|
||||
require('./libraries/jquery.ba-throttle-debounce');
|
||||
|
||||
const { app } = require('@electron/remote');
|
||||
const d3 = require('./libraries/d3.min.js');
|
||||
const d3 = require('./libraries/d3.min');
|
||||
const Store = require('electron-store');
|
||||
const store = new Store();
|
||||
|
||||
|
@ -14,15 +14,15 @@ const { GUI, TABS } = require('./gui');
|
|||
const CONFIGURATOR = require('./data_storage');
|
||||
const FC = require('./fc');
|
||||
const { globalSettings, UnitType } = require('./globalSettings');
|
||||
const { PLATFORM } = require('./model.js')
|
||||
const { PLATFORM } = require('./model')
|
||||
const i18n = require('./localization');
|
||||
const SerialBackend = require('./serial_backend');
|
||||
const MSP = require('./msp');
|
||||
const MSPCodes = require('./../js/msp/MSPCodes');
|
||||
const mspHelper = require('./msp/MSPHelper.js');
|
||||
const update = require('./globalUpdates.js');
|
||||
const appUpdater = require('./appUpdater.js');
|
||||
const CliAutoComplete = require('./CliAutoComplete.js');
|
||||
const mspHelper = require('./msp/MSPHelper');
|
||||
const update = require('./globalUpdates');
|
||||
const appUpdater = require('./appUpdater');
|
||||
const CliAutoComplete = require('./CliAutoComplete');
|
||||
const { SITLProcess } = require('./sitl');
|
||||
;
|
||||
process.on('uncaughtException', function (error) {
|
||||
|
@ -229,19 +229,19 @@ $(function() {
|
|||
TABS.modes.initialize(content_ready);
|
||||
break;
|
||||
case 'gps':
|
||||
require('./../tabs/gps.js');
|
||||
require('./../tabs/gps');
|
||||
TABS.gps.initialize(content_ready);
|
||||
break;
|
||||
case 'magnetometer':
|
||||
require('./../tabs/magnetometer.js');
|
||||
require('./../tabs/magnetometer');
|
||||
TABS.magnetometer.initialize(content_ready);
|
||||
break;
|
||||
case 'mission_control':
|
||||
require('./../tabs/mission_control.js');
|
||||
require('./../tabs/mission_control');
|
||||
TABS.mission_control.initialize(content_ready);
|
||||
break;
|
||||
case 'mixer':
|
||||
require('./../tabs/mixer.js');
|
||||
require('./../tabs/mixer');
|
||||
TABS.mixer.initialize(content_ready);
|
||||
break;
|
||||
case 'outputs':
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
'use strict';
|
||||
|
||||
const { GUI } = require('./../js/gui');
|
||||
const FC = require('./fc.js');
|
||||
const FC = require('./fc');
|
||||
const MSP = require('./msp');
|
||||
const MSPCodes = require('./../js/msp/MSPCodes');
|
||||
const mspHelper = require('./msp/MSPHelper');
|
||||
const MSPChainerClass = require('./msp/MSPchainer.js');
|
||||
const MSPChainerClass = require('./msp/MSPchainer');
|
||||
const features = require('./feature_framework');
|
||||
const periodicStatusUpdater = require('./periodicStatusUpdater.js');
|
||||
const periodicStatusUpdater = require('./periodicStatusUpdater');
|
||||
const { mixer } = require('./model');
|
||||
const jBox = require('./libraries/jBox/jBox.min.js');
|
||||
const i18n = require('./localization.js');
|
||||
const jBox = require('./libraries/jBox/jBox.min');
|
||||
const i18n = require('./localization');
|
||||
|
||||
var savingDefaultsModal;
|
||||
|
||||
|
|
6
js/fc.js
6
js/fc.js
|
@ -10,8 +10,8 @@ const ProgrammingPidStatus = require('./programmingPidStatus');
|
|||
const WaypointCollection = require('./waypointCollection');
|
||||
const OutputMappingCollection = require('./outputMapping');
|
||||
const SafehomeCollection = require('./safehomeCollection');
|
||||
const FwApproachCollection = require('./fwApproachCollection.js')
|
||||
const { PLATFORM } = require('./model.js')
|
||||
const FwApproachCollection = require('./fwApproachCollection')
|
||||
const { PLATFORM } = require('./model')
|
||||
const VTX = require('./vtx');
|
||||
const BitHelper = require('./bitHelper');
|
||||
|
||||
|
@ -94,7 +94,7 @@ var FC = {
|
|||
return (this.MIXER_CONFIG.platformType == PLATFORM.AIRPLANE);
|
||||
},
|
||||
isMultirotor: function () {
|
||||
return (this.MIXER_CONFIG.platformType == PLATFORM.MULTIROTOR || MIXER_CONFIG.platformType == PLATFORM.TRICOPTER);
|
||||
return (this.MIXER_CONFIG.platformType == PLATFORM.MULTIROTOR || this.MIXER_CONFIG.platformType == PLATFORM.TRICOPTER);
|
||||
},
|
||||
isRpyFfComponentUsed: function () {
|
||||
return true; // Currently all planes have roll, pitch and yaw FF
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const ol = require('openlayers');
|
||||
|
||||
const { GUI } = require('./gui');
|
||||
|
@ -139,7 +140,7 @@ const groundstation = (function () {
|
|||
anchor: [0.5, 0.5],
|
||||
opacity: 1,
|
||||
scale: 0.6,
|
||||
src: '../images/icons/icon_mission_airplane.png'
|
||||
src: path.join(__dirname, './../images/icons/icon_mission_airplane.png')
|
||||
}))
|
||||
});
|
||||
privateScope.cursorPosition = new ol.geom.Point(ol.proj.fromLonLat([lon, lat]));
|
||||
|
|
|
@ -21,12 +21,12 @@ const timeout = require('./timeouts');
|
|||
const mspBalancedInterval = require('./msp_balanced_interval');
|
||||
const defaultsDialog = require('./defaults_dialog');
|
||||
const { SITLProcess } = require('./sitl');
|
||||
const update = require('./globalUpdates.js');
|
||||
const BitHelper = require('./bitHelper.js');
|
||||
const BOARD = require('./boards.js');
|
||||
const jBox = require('./libraries/jBox/jBox.min.js');
|
||||
const groundstation = require('./groundstation.js');
|
||||
const ltmDecoder = require('./ltmDecoder.js');
|
||||
const update = require('./globalUpdates');
|
||||
const BitHelper = require('./bitHelper');
|
||||
const BOARD = require('./boards');
|
||||
const jBox = require('./libraries/jBox/jBox.min');
|
||||
const groundstation = require('./groundstation');
|
||||
const ltmDecoder = require('./ltmDecoder');
|
||||
|
||||
var SerialBackend = (function () {
|
||||
|
||||
|
|
|
@ -211,7 +211,7 @@ var SITLProcess = {
|
|||
sitlExePath = path.join(__dirname, './../resources/sitl/windows/inav_SITL.exe');
|
||||
eepromPath = `${app.getPath('userData')}\\${eepromFileName}`
|
||||
} else if (GUI.operating_system == 'Linux') {
|
||||
sitlExePath = './../resources/sitl/linux/inav_SITL';
|
||||
sitlExePath = path.join(__dirname, './../resources/sitl/linux/inav_SITL');
|
||||
eepromPath = `${app.getPath('userData')}/${eepromFileName}`
|
||||
chmod(sitlExePath, 0o755, err => {
|
||||
if (err)
|
||||
|
|
|
@ -421,7 +421,7 @@ let WaypointCollection = function () {
|
|||
self.getElevation = async function(globalSettings) {
|
||||
const [nLoop, point2measure, altPoint2measure, namePoint2measure, refPoint2measure] = self.getPoint2Measure(true);
|
||||
let lengthMission = self.getDistance(true);
|
||||
let totalMissionDistance = lengthMission[lengthMission.length -1].toFixed(1);
|
||||
let totalMissionDistance = lengthMission.length >= 1 ? lengthMission[lengthMission.length -1].toFixed(1) : 0;
|
||||
let samples;
|
||||
let sampleMaxNum;
|
||||
let sampleDistance;
|
||||
|
|
885
package-lock.json
generated
885
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -45,8 +45,9 @@
|
|||
"@electron-forge/cli": "^7.2.0",
|
||||
"@electron-forge/maker-deb": "^7.2.0",
|
||||
"@electron-forge/maker-rpm": "^7.2.0",
|
||||
"@electron-forge/maker-squirrel": "^7.2.0",
|
||||
"@electron-forge/maker-zip": "^7.2.0",
|
||||
"@electron-forge/maker-dmg": "^7.2.0",
|
||||
"@electron-forge/maker-wix": "^7.2.0",
|
||||
"electron": "28.1.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,7 +249,7 @@
|
|||
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.35);
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
background-image: url(/images/icons/cf_icon_sdcard.svg);
|
||||
background-image: url(./../../../images/icons/cf_icon_sdcard.svg);
|
||||
background-position: 21px 20px;
|
||||
background-size: 50px 50px;
|
||||
background-repeat: no-repeat;
|
||||
|
|
|
@ -9,9 +9,9 @@ const MSP = require('./../js/msp');
|
|||
const { GUI, TABS } = require('./../js/gui');
|
||||
const FC = require('./../js/fc');
|
||||
const timeout = require('./../js/timeouts');
|
||||
const interval = require('./../js/intervals.js');
|
||||
const interval = require('./../js/intervals');
|
||||
const i18n = require('./../js/localization');
|
||||
const jBox = require('./../js/libraries/jBox/jBox.min.js');
|
||||
const jBox = require('./../js/libraries/jBox/jBox.min');
|
||||
|
||||
TABS.calibration = {};
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ const i18n = require('./../js/localization');
|
|||
const { globalSettings } = require('./../js/globalSettings');
|
||||
const CliAutoComplete = require('./../js/CliAutoComplete');
|
||||
const { ConnectionType } = require('./../js/connection/connection');
|
||||
const jBox = require('./../js/libraries/jBox/jBox.min.js');
|
||||
const jBox = require('./../js/libraries/jBox/jBox.min');
|
||||
|
||||
TABS.cli = {
|
||||
lineDelayMs: 50,
|
||||
|
|
10
tabs/gps.js
10
tabs/gps.js
|
@ -8,8 +8,8 @@ const MSPChainerClass = require('./../js/msp/MSPchainer');
|
|||
const mspHelper = require('./../js/msp/MSPHelper');
|
||||
const MSPCodes = require('./../js/msp/MSPCodes');
|
||||
const MSP = require('./../js/msp');
|
||||
const mspBalancedInterval = require('./../js/msp_balanced_interval.js');
|
||||
const mspQueue = require('./../js/serial_queue.js');
|
||||
const mspBalancedInterval = require('./../js/msp_balanced_interval');
|
||||
const mspQueue = require('./../js/serial_queue');
|
||||
const { GUI, TABS } = require('./../js/gui');
|
||||
const FC = require('./../js/fc');
|
||||
const i18n = require('./../js/localization');
|
||||
|
@ -17,7 +17,7 @@ const Settings = require('./../js/settings');
|
|||
const serialPortHelper = require('./../js/serialPortHelper');
|
||||
const features = require('./../js/feature_framework');
|
||||
const { globalSettings } = require('./../js/globalSettings');
|
||||
const jBox = require('./../js/libraries/jBox/jBox.min.js');
|
||||
const jBox = require('./../js/libraries/jBox/jBox.min');
|
||||
const SerialBackend = require('../js/serial_backend');
|
||||
|
||||
|
||||
|
@ -307,7 +307,7 @@ TABS.gps.initialize = function (callback) {
|
|||
anchor: [0.5, 1],
|
||||
opacity: 1,
|
||||
scale: 0.5,
|
||||
src: '../../images/icons/cf_icon_position.png'
|
||||
src: path.join(__dirname, './../images/icons/cf_icon_position.png')
|
||||
}))
|
||||
});
|
||||
|
||||
|
@ -366,7 +366,7 @@ TABS.gps.initialize = function (callback) {
|
|||
rotation: vehicle.headingDegrees * (Math.PI / 180),
|
||||
scale: 0.8,
|
||||
anchor: [0.5, 0.5],
|
||||
src: '../resources/adsb/' + ADSB_VEHICLE_TYPE[vehicle.emitterType],
|
||||
src: path.join(__dirname, './../resources/adsb/' + ADSB_VEHICLE_TYPE[vehicle.emitterType]),
|
||||
})),
|
||||
text: new ol.style.Text(({
|
||||
text: vehicle.callsign,
|
||||
|
|
|
@ -10,8 +10,8 @@ const MSPChainerClass = require('./../js/msp/MSPchainer');
|
|||
const mspHelper = require('./../js/msp/MSPHelper');
|
||||
const MSPCodes = require('./../js/msp/MSPCodes');
|
||||
const MSP = require('./../js/msp');
|
||||
const mspBalancedInterval = require('./../js/msp_balanced_interval.js');
|
||||
const mspQueue = require('./../js/serial_queue.js');
|
||||
const mspBalancedInterval = require('./../js/msp_balanced_interval');
|
||||
const mspQueue = require('./../js/serial_queue');
|
||||
const { GUI, TABS } = require('./../js/gui');
|
||||
const FC = require('./../js/fc');
|
||||
const CONFIGURATOR = require('./../js/data_storage');
|
||||
|
@ -24,9 +24,9 @@ const Safehome = require('./../js/safehome');
|
|||
const SafehomeCollection = require('./../js/safehomeCollection');
|
||||
const { ApproachDirection, FwApproach } = require('./../js/fwApproach');
|
||||
const FwApproachCollection = require('./../js/fwApproachCollection');
|
||||
const SerialBackend = require('./../js/serial_backend.js');
|
||||
const SerialBackend = require('./../js/serial_backend');
|
||||
const { distanceOnLine, wrap_360, calculate_new_cooridatnes } = require('./../js/helpers');
|
||||
const Plotly = require('./../js/libraries/plotly-latest.min.js');
|
||||
const Plotly = require('./../js/libraries/plotly-latest.min');
|
||||
|
||||
var MAX_NEG_FW_LAND_ALT = -2000; // cm
|
||||
|
||||
|
@ -68,7 +68,6 @@ TABS.mission_control.initialize = function (callback) {
|
|||
var textGeom;
|
||||
let isOffline = false;
|
||||
let selectedSafehome;
|
||||
let rthUpdateInterval = 0;
|
||||
let $safehomeContentBox;
|
||||
let $waypointOptionsTableBody;
|
||||
let settings = {speed: 0, alt: 5000, safeRadiusSH: 50, fwApproachAlt: 60, fwLandAlt: 5, maxDistSH: 0, fwApproachLength: 0, fwLoiterRadius: 0, bingDemModel: false};
|
||||
|
@ -326,18 +325,6 @@ TABS.mission_control.initialize = function (callback) {
|
|||
'\nAlt: ' + FC.SENSOR_DATA.altitude +
|
||||
'm\nSpeed: ' + FC.GPS_DATA.speed + 'cm/s\n' +
|
||||
'Dist: ' + FC.GPS_DATA.distanceToHome + 'm');
|
||||
|
||||
//update RTH every 5th GPS update since it really shouldn't change
|
||||
if(rthUpdateInterval >= 5)
|
||||
{
|
||||
FC.MISSION_PLANNER.bufferPoint.number = -1; //needed to get point 0 which id RTH
|
||||
MSP.send_message(MSPCodes.MSP_WP, mspHelper.crunch(MSPCodes.MSP_WP), false, function rth_update() {
|
||||
var coord = ol.proj.fromLonLat([FC.MISSION_PLANNER.bufferPoint.lon, FC.MISSION_PLANNER.bufferPoint.lat]);
|
||||
rthGeo.setCoordinates(coord);
|
||||
});
|
||||
rthUpdateInterval = 0;
|
||||
}
|
||||
rthUpdateInterval++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1276,7 +1263,11 @@ TABS.mission_control.initialize = function (callback) {
|
|||
if (disableMarkerEdit) {
|
||||
$('#missionDistance').text('N/A');
|
||||
} else {
|
||||
$('#missionDistance').text(lengthMission[lengthMission.length -1] != -1 ? lengthMission[lengthMission.length -1].toFixed(1) : 'infinite');
|
||||
if (lengthMission.length >= 1) {
|
||||
$('#missionDistance').text(lengthMission[lengthMission.length -1].toFixed(1));
|
||||
} else {
|
||||
$('#missionDistance').text('infinite');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ const i18n = require('./../js/localization');
|
|||
const { mixer, platform, PLATFORM, INPUT, STABILIZED } = require('./../js/model');
|
||||
const Settings = require('./../js/settings');
|
||||
const mspBalancedInterval = require('./../js/msp_balanced_interval');
|
||||
const jBox = require('../js/libraries/jBox/jBox.min.js');
|
||||
const jBox = require('../js/libraries/jBox/jBox.min');
|
||||
|
||||
TABS.mixer = {};
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ const Settings = require('./../js/settings');
|
|||
const { globalSettings } = require('./../js/globalSettings');
|
||||
const { PortHandler } = require('./../js/port_handler');
|
||||
const i18n = require('./../js/localization');
|
||||
const jBox = require('./../js/libraries/jBox/jBox.min.js');
|
||||
const jBox = require('./../js/libraries/jBox/jBox.min');
|
||||
|
||||
|
||||
var SYM = SYM || {};
|
||||
|
|
|
@ -5,18 +5,18 @@ const path = require('path');
|
|||
const MSPChainerClass = require('./../js/msp/MSPchainer');
|
||||
const mspHelper = require('./../js/msp/MSPHelper');
|
||||
const MSPCodes = require('./../js/msp/MSPCodes');
|
||||
const mspBalancedInterval = require('./../js/msp_balanced_interval.js');
|
||||
const mspQueue = require('./../js/serial_queue.js')
|
||||
const mspBalancedInterval = require('./../js/msp_balanced_interval');
|
||||
const mspQueue = require('./../js/serial_queue')
|
||||
const MSP = require('./../js/msp');
|
||||
const { GUI, TABS } = require('./../js/gui');
|
||||
const FC = require('./../js/fc');
|
||||
const i18n = require('./../js/localization');
|
||||
const BitHelper = require('../js/bitHelper');
|
||||
const Settings = require('./../js/settings.js');
|
||||
const features = require('./../js/feature_framework.js');
|
||||
const Settings = require('./../js/settings');
|
||||
const features = require('./../js/feature_framework');
|
||||
const { mixer, PLATFORM } = require('./../js/model');
|
||||
const timeout = require('./../js/timeouts.js')
|
||||
const interval = require('./../js/intervals.js');
|
||||
const timeout = require('./../js/timeouts')
|
||||
const interval = require('./../js/intervals');
|
||||
|
||||
TABS.outputs = {
|
||||
allowTestMode: false,
|
||||
|
|
|
@ -120,7 +120,7 @@ TABS.sitl.initialize = (callback) => {
|
|||
|
||||
var $sitlLog = $('#sitlLog');
|
||||
$sitlLog.val(SITL_LOG);
|
||||
if ($sitlLog) {
|
||||
if ($sitlLog && $sitlLog.length == 1) {
|
||||
$sitlLog.val(SITL_LOG);
|
||||
$sitlLog.animate({scrollTop: $sitlLog[0].scrollHeight - $sitlLog.height()}, "fast");
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ TABS.sitl.initialize = (callback) => {
|
|||
function appendLog(message){
|
||||
SITL_LOG += message;
|
||||
var $sitlLog = $('#sitlLog');
|
||||
if ($sitlLog) {
|
||||
if ($sitlLog && $sitlLog.length == 1) {
|
||||
$sitlLog.val(SITL_LOG);
|
||||
$sitlLog.animate({scrollTop: $sitlLog[0].scrollHeight - $sitlLog.height()}, "fast");
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue