kopia lustrzana https://gitlab.com/gridtracker.org/gridtracker
Merge branch 'master' into rich-presence
commit
ad30b9cda0
|
@ -10,3 +10,5 @@ debian/tmp
|
|||
.DS_Store
|
||||
node_modules
|
||||
package-lock.json
|
||||
.vscode
|
||||
desktop.ini
|
358
.gitlab-ci.yml
358
.gitlab-ci.yml
|
@ -2,7 +2,7 @@
|
|||
# see https://docs.gitlab.com/ee/ci/yaml/README.html for all available options
|
||||
|
||||
variables:
|
||||
DEFAULT_IMAGE: debian:stable
|
||||
DEFAULT_IMAGE: registry.gitlab.com/gridtracker.org/gtbuilder:v1-0
|
||||
APT_CACHE_DIR: $CI_PROJECT_DIR/.cache/apt
|
||||
NPM_CONFIG_CACHE: $CI_PROJECT_DIR/.cache/npm
|
||||
|
||||
|
@ -10,23 +10,37 @@ variables:
|
|||
# We have code in here for releasing on both GS and S3, control it through variables
|
||||
# on GitLab, do not change it in this file.
|
||||
#
|
||||
GCLOUD_PROJECT_ID: "cent7-288417"
|
||||
GCLOUD_SERVICE_ACCOUNT: /dev/null
|
||||
GCLOUD_RELEASE_DEPLOY_PATH: gs://download.gridtracker.org/release/$CI_COMMIT_TAG
|
||||
GCLOUD_TESTING_DEPLOY_PATH: gs://download.gridtracker.org/testing/$CI_COMMIT_TAG
|
||||
GCLOUD_DEPLOY_PATH: gs://gt_download/$CI_COMMIT_TAG
|
||||
NR0Q_SERVER_ADDRESS: ""
|
||||
NR0Q_SERVER_PASSWORD: ""
|
||||
|
||||
#
|
||||
# Because it's getting to be that kind of world, we're going to have to
|
||||
# sign our packages/exectuables with a signing key.
|
||||
# That signing chain and spec file will be stored in a Gitlab CI Variable and protected,
|
||||
# here's a placeholder for the script
|
||||
G_CODE_SIGNING_CHAIN: ""
|
||||
|
||||
# nothing in this file ill be allowed to run automatically except for:
|
||||
# 1. merge requests
|
||||
# 2. manual tagging
|
||||
# 3. committing to the default branch
|
||||
include:
|
||||
- template: "Workflows/MergeRequest-Pipelines.gitlab-ci.yml"
|
||||
- template: "Security/Dependency-Scanning.gitlab-ci.yml"
|
||||
- template: "Security/Secret-Detection.gitlab-ci.yml"
|
||||
- template: "Security/SAST.gitlab-ci.yml"
|
||||
|
||||
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- staging
|
||||
- package
|
||||
- pre-deploy
|
||||
- deploy
|
||||
|
||||
default:
|
||||
|
@ -35,7 +49,7 @@ default:
|
|||
|
||||
# just do a quick syntax check job, we don't need to "build" anything here other than the
|
||||
# outer dev environment for gridtracker
|
||||
npm_test:
|
||||
npm:test:
|
||||
stage: test
|
||||
image: node:latest
|
||||
script:
|
||||
|
@ -49,7 +63,7 @@ npm_test:
|
|||
# - echo "For example run a lint test"
|
||||
|
||||
# package binaries and create build artifacts that may be used in later stages
|
||||
win-packaging:
|
||||
win:package:
|
||||
stage: package
|
||||
rules:
|
||||
# only do this with a manual tag starting with v or test_
|
||||
|
@ -66,55 +80,53 @@ win-packaging:
|
|||
files:
|
||||
- package.json
|
||||
- package.nw/package.json
|
||||
before_script:
|
||||
- |
|
||||
mkdir -p $NPM_CONFIG_CACHE
|
||||
mkdir -p artifacts
|
||||
echo -e "\e[0Ksection_start:`date +%s`:apt_get[collapsed=true]\r\e[0KGetting Build Dependencies"
|
||||
apt-get update && apt-get upgrade -y
|
||||
apt-get install p7zip -y
|
||||
wget https://nsis.sourceforge.io/mediawiki/images/4/47/Registry.zip
|
||||
unzip -bj Registry.zip Desktop/Plugin/registry.dll -d /usr/share/nsis/Plugins/x86-unicode/
|
||||
unzip -bj Registry.zip Desktop/Include/Registry.nsh -d /usr/share/nsis/Include/
|
||||
wget https://nsis.sourceforge.io/mediawiki/images/1/18/NsProcess.zip
|
||||
7zr e NsProcess.zip -y -o/usr/share/nsis/Include/ Include/nsProcess.nsh
|
||||
7zr e NsProcess.zip -y -o/usr/share/nsis/Plugins/x86-unicode/ Plugin/nsProcessW.dll
|
||||
mv /usr/share/nsis/Plugins/x86-unicode/nsProcessW.dll /usr/share/nsis/Plugins/x86-unicode/nsProcess.dll
|
||||
## eval $(ssh-agent -s)
|
||||
## echo "$NR0Q_PRIV" | tr -d '\r' | ssh-add -
|
||||
## mkdir -p ~/.ssh; chmod 700 ~/.ssh
|
||||
## scp -o StrictHostKeyChecking=no -P $NR0Q_SSH_PORT mchambers@$NR0Q_SERVER_ADDRESS:~/codecert.spc ./
|
||||
script:
|
||||
- |
|
||||
mkdir -p $APT_CACHE_DIR $NPM_CONFIG_CACHE
|
||||
mkdir -p artifacts
|
||||
dpkg --add-architecture i386
|
||||
- |
|
||||
echo -e "\e[0Ksection_start:`date +%s`:apt_get[collapsed=true]\r\e[0KGetting Build Dependencies"
|
||||
apt-get -qq update
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y npm wine wine32
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y build-essential devscripts
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y zip nsis nsis nsis-pluginapi wget
|
||||
wget https://nsis.sourceforge.io/mediawiki/images/4/47/Registry.zip
|
||||
unzip Registry.zip
|
||||
mv Desktop/Plugin/registry.dll /usr/share/nsis/Plugins/x86-unicode/
|
||||
mv Desktop/Include/Registry.nsh /usr/share/nsis/Include/
|
||||
rm -Rf Desktop PocketPC Source
|
||||
# Making our Windows packages
|
||||
echo -e "\e[0Ksection_end:`date +%s`:apt_get\r\e[0K"
|
||||
- test `node version.js` = `dpkg-parsechangelog -S version` || (echo "package.nw/package.json and debian/changelog version mismatch"; exit 1)
|
||||
# Making our Windows packages
|
||||
- |
|
||||
test `node version.js` = `dpkg-parsechangelog -S version` || (echo "package.nw/package.json and debian/changelog version mismatch"; exit 1)
|
||||
echo -e "\e[0Ksection_start:`date +%s`:native_build\r\e[0KBuilding native packages"
|
||||
npm install --prefer-offline
|
||||
npm run dist-win
|
||||
for dir in dist/*-win-* ; do
|
||||
if [ -d $dir ] ; then
|
||||
rm $dir/locales/*.info
|
||||
mkdir $dir/package.nw
|
||||
for file in package.nw/* ; do
|
||||
mv $dir/`basename $file` $dir/package.nw
|
||||
done
|
||||
elif [ -f $dir ] && [[ "$dir" == *"win-x86-Setup.exe"* ]] ; then
|
||||
if [ -f $dir ] && [[ "$dir" == *"-Setup.exe" ]] ; then
|
||||
echo "deleting broken installer $dir"
|
||||
rm $dir
|
||||
fi
|
||||
done
|
||||
sed "s#GridTracker-\${VERSION}-win-x86/#`pwd`/dist/GridTracker-\${VERSION}-win-x86/#g" windows/setup.nsi.tmpl > windows/setup.nsi.tmp.1
|
||||
sed "s#GridTracker-Installer.#`pwd`/dist/GridTracker-Installer.#g" windows/setup.nsi.tmp.1 > windows/setup.nsi.tmp.2
|
||||
sed "s#define VERSION <placeholder#define VERSION `node version.js`#g" windows/setup.nsi.tmp.2 > windows/setup.nsi
|
||||
|
||||
# Now we need to sign the executable before it get's stuffed into Nullsoft
|
||||
# using mono signcode
|
||||
## signcode -spc codecert.spc -t http://time.certum.pl/ -a sha256 dist/GridTracker-*-win-*/*.exe
|
||||
# Now the executable should be signed
|
||||
sed "s#<versionplaceholder>#`node version.js`#g" windows/win_installer.nsi > windows/setup.nsi.tmp.1
|
||||
sed "s#<buildplaceholder>#`pwd`#g" windows/setup.nsi.tmp.1 > windows/setup.nsi
|
||||
makensis windows/setup.nsi
|
||||
# clean up generated files
|
||||
rm windows/setup.nsi
|
||||
rm windows/setup.nsi.tmp.1
|
||||
rm windows/setup.nsi.tmp.2
|
||||
## signcode -spc codecert.spc -t http://time.certum.pl/ -a sha256 dist/GridTracker-Installer.*.exe
|
||||
(cd dist ; mv GridTracker-Installer.*.exe ../artifacts)
|
||||
echo -e "\e[0Ksection_end:`date +%s`:native_build\e[0K"
|
||||
|
||||
|
||||
intel-packaging:
|
||||
linux:package:
|
||||
stage: package
|
||||
rules:
|
||||
# only do this with a manual tag starting with v or test_
|
||||
|
@ -131,22 +143,17 @@ intel-packaging:
|
|||
files:
|
||||
- package.json
|
||||
- package.nw/package.json
|
||||
before_script:
|
||||
- |
|
||||
mkdir -p $NPM_CONFIG_CACHE
|
||||
mkdir -p artifacts
|
||||
echo -e "\e[0Ksection_start:`date +%s`:apt_get[collapsed=true]\r\e[0KGetting Build Dependencies"
|
||||
apt-get update && apt-get upgrade -y
|
||||
echo -e "\e[0Ksection_end:`date +%s`:apt_get\r\e[0K"
|
||||
script:
|
||||
- |
|
||||
mkdir -p $APT_CACHE_DIR $NPM_CONFIG_CACHE
|
||||
mkdir -p artifacts/rpm
|
||||
dpkg --add-architecture i386
|
||||
- |
|
||||
echo -e "\e[0Ksection_start:`date +%s`:apt_get[collapsed=true]\r\e[0KGetting Build Dependencies"
|
||||
apt-get -qq update
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y npm wine wine32
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y build-essential devscripts
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y rpm zip wget
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" build-dep .
|
||||
echo -e "\e[0Ksection_end:`date +%s`:apt_get\r\e[0K"
|
||||
- test `node version.js` = `dpkg-parsechangelog -S version` || (echo "package.nw/package.json and debian/changelog version mismatch"; exit 1)
|
||||
# Making our MacOS and distro agnostic Linux packages
|
||||
- |
|
||||
# Making our distro agnostic Linux packages
|
||||
test `node version.js` = `dpkg-parsechangelog -S version` || (echo "package.nw/package.json and debian/changelog version mismatch"; exit 1)
|
||||
echo -e "\e[0Ksection_start:`date +%s`:native_build\r\e[0KBuilding native packages"
|
||||
npm install --prefer-offline
|
||||
npm run dist-nix
|
||||
|
@ -158,30 +165,17 @@ intel-packaging:
|
|||
tar -C dist -czf ${dir}.tar.gz `basename $dir`
|
||||
fi
|
||||
done
|
||||
(cd dist ; mv *-mac-x64.zip *.tar.gz ../artifacts)
|
||||
(cd dist; mv *.tar.gz ../artifacts/)
|
||||
echo -e "\e[0Ksection_end:`date +%s`:native_build\e[0K"
|
||||
# This section handles making RPMs for Fedora/CentOS/RHEL
|
||||
- |
|
||||
echo -e "\e[0Ksection_start:`date +%s`:rpm_build\r\e[0KBuilding RPM packages"
|
||||
# mkdir -p $HOME/rpmbuild/SOURCES
|
||||
# cp artifacts/*.tar.gz $HOME/rpmbuild/SOURCES/
|
||||
setarch i386 rpmbuild -D "version `node ./version.js`" --build-in-place -bb gridtracker.i386.spec
|
||||
setarch x86_64 rpmbuild -D "version `node ./version.js`" --build-in-place -bb gridtracker.x86_64.spec
|
||||
mv $HOME/rpmbuild/RPMS/i386/*.rpm artifacts/rpm/
|
||||
mv $HOME/rpmbuild/RPMS/x86_64/*.rpm artifacts/rpm/
|
||||
echo -e "\e[0Ksection_end:`date +%s`:rpm_build\r\e[0K"
|
||||
# This section does debian DEBs
|
||||
#- |
|
||||
# echo -e "\e[0Ksection_start:`date +%s`:debian_build\r\e[0KBuilding Debian packages"
|
||||
# dpkg-buildpackage -uc -us
|
||||
# mkdir artifacts/debian
|
||||
# mv ../*.{deb,dsc,buildinfo,tar.xz,changes} artifacts/debian/
|
||||
# echo -e "\e[0Ksection_end:`date +%s`:debian_build\r\e[0K"
|
||||
- |
|
||||
echo "we made packages!"
|
||||
# This section does debian DEBs
|
||||
echo -e "\e[0Ksection_start:`date +%s`:debian_build\r\e[0KBuilding Debian packages"
|
||||
dpkg-buildpackage -b --no-sign
|
||||
mv ../*.{deb,buildinfo,changes} artifacts/
|
||||
echo -e "\e[0Ksection_end:`date +%s`:debian_build\r\e[0K"
|
||||
echo "we made LINUX packages!"
|
||||
ls -laR artifacts
|
||||
|
||||
arm-packaging:
|
||||
mac:package:
|
||||
stage: package
|
||||
rules:
|
||||
# only do this with a manual tag starting with v or test_
|
||||
|
@ -198,118 +192,114 @@ arm-packaging:
|
|||
files:
|
||||
- package.json
|
||||
- package.nw/package.json
|
||||
before_script:
|
||||
- |
|
||||
mkdir -p $NPM_CONFIG_CACHE
|
||||
mkdir -p artifacts
|
||||
echo -e "\e[0Ksection_start:`date +%s`:apt_get[collapsed=true]\r\e[0KGetting Build Dependencies"
|
||||
apt-get update && apt-get upgrade -y
|
||||
echo -e "\e[0Ksection_end:`date +%s`:apt_get\r\e[0K"
|
||||
script:
|
||||
- |
|
||||
mkdir -p $APT_CACHE_DIR $NPM_CONFIG_CACHE
|
||||
mkdir -p artifacts/rpm
|
||||
dpkg --add-architecture armhf
|
||||
- |
|
||||
echo -e "\e[0Ksection_start:`date +%s`:apt_get[collapsed=true]\r\e[0KGetting Build Dependencies"
|
||||
apt-get -qq update
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y npm
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y build-essential devscripts
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" install -y rpm zip wget
|
||||
apt-get -qq -o dir::cache::archives="$APT_CACHE_DIR" build-dep .
|
||||
echo -e "\e[0Ksection_end:`date +%s`:apt_get\r\e[0K"
|
||||
- test `node version.js` = `dpkg-parsechangelog -S version` || (echo "package.nw/package.json and debian/changelog version mismatch"; exit 1)
|
||||
# This is for ARM arch build
|
||||
- |
|
||||
echo -e "\e[0Ksection_start:`date +%s`:arm_build\r\e[0KBuilding ARM packages"
|
||||
wget https://github.com/LeonardLaszlo/nw.js-armv7-binaries/releases/download/nw49_2020-10-26/nw49_2020-10-26.tar.gz
|
||||
tar -xf nw49_2020-10-26.tar.gz
|
||||
tar -xf usr/docker/dist/nwjs-chromium-ffmpeg-branding/nwjs-v0.49.2-linux-arm.tar.gz
|
||||
rm nwjs-v0.49.2-linux-arm/locales/*.info
|
||||
mv nwjs-v0.49.2-linux-arm/nw nwjs-v0.49.2-linux-arm/GridTracker
|
||||
ls
|
||||
version=`node ./version.js`
|
||||
mkdir GridTracker-$version-linux-arm
|
||||
cp -r nwjs-v0.49.2-linux-arm/* GridTracker-$version-linux-arm/
|
||||
cp -r arm/* GridTracker-$version-linux-arm/
|
||||
cp -r package.nw GridTracker-$version-linux-arm/
|
||||
cp LICENSE GridTracker-$version-linux-arm/
|
||||
tar -czf GridTracker-$version-linux-arm.tar.gz GridTracker-$version-linux-arm
|
||||
mv GridTracker-$version-linux-arm.tar.gz artifacts/
|
||||
# This section handles making RPMs for Fedora/CentOS/RHEL
|
||||
#- |
|
||||
# echo -e "\e[0Ksection_start:`date +%s`:rpm_build\r\e[0KBuilding RPM packages"
|
||||
# mkdir -p $HOME/rpmbuild/SOURCES
|
||||
# cp artifacts/*.tar.gz $HOME/rpmbuild/SOURCES/
|
||||
#setarch --list
|
||||
#setarch armhf rpmbuild -D "version `node ./version.js`" --build-in-place -bb gridtracker.arm.spec
|
||||
#mv $HOME/rpmbuild/RPMS/armv7l/*.rpm artifacts/rpm/
|
||||
#echo -e "\e[0Ksection_end:`date +%s`:rpm_build\r\e[0K"
|
||||
# This section does debian DEBs
|
||||
#- |
|
||||
# echo -e "\e[0Ksection_start:`date +%s`:debian_build\r\e[0KBuilding Debian packages"
|
||||
# dpkg-buildpackage -uc -us
|
||||
# mkdir artifacts/debian
|
||||
# mv ../*.{deb,dsc,buildinfo,tar.xz,changes} artifacts/debian/
|
||||
# echo -e "\e[0Ksection_end:`date +%s`:debian_build\r\e[0K"
|
||||
- |
|
||||
echo "we made packages!"
|
||||
# Making our MacOS packages
|
||||
test `node version.js` = `dpkg-parsechangelog -S version` || (echo "package.nw/package.json and debian/changelog version mismatch"; exit 1)
|
||||
echo -e "\e[0Ksection_start:`date +%s`:native_build\r\e[0KBuilding native packages"
|
||||
npm install --prefer-offline
|
||||
npm run dist-mac
|
||||
(cd dist; mv *.zip ../artifacts/)
|
||||
echo -e "\e[0Ksection_end:`date +%s`:native_build\e[0K"
|
||||
echo "we made MAC packages!"
|
||||
ls -laR artifacts
|
||||
|
||||
# copy test assets to NR0Q's server
|
||||
nr0q_upload_testing:
|
||||
stage: deploy
|
||||
image: alpine
|
||||
arm:package:
|
||||
stage: package
|
||||
variables:
|
||||
NWJS_VERSION: "v0.54.2"
|
||||
NWJS32_BUILD: "nw54_2021-07-09"
|
||||
NWJS64_BUILD: "nw54-arm64_2021-07-10"
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG =~ /^(test_).*/ && $NR0Q_SERVER_KEY != ""'
|
||||
# only do this with a manual tag starting with v or test_
|
||||
- if: '$CI_COMMIT_TAG =~ /^(v|test_).*/'
|
||||
artifacts:
|
||||
paths:
|
||||
- artifacts/
|
||||
name: '$CI_COMMIT_REF_SLUG'
|
||||
cache:
|
||||
paths:
|
||||
- .cache/
|
||||
- node_modules/
|
||||
key:
|
||||
files:
|
||||
- package.json
|
||||
- package.nw/package.json
|
||||
before_script:
|
||||
- |
|
||||
apk add openssh-client
|
||||
eval $(ssh-agent -s)
|
||||
echo "$NR0Q_SERVER_KEY" | tr -d '\r' | ssh-add -
|
||||
mkdir -p ~/.ssh; chmod 700 ~/.ssh
|
||||
mkdir -p $NPM_CONFIG_CACHE
|
||||
mkdir -p artifacts
|
||||
#dpkg --add-architecture armhf
|
||||
echo -e "\e[0Ksection_start:`date +%s`:apt_get[collapsed=true]\r\e[0KGetting Build Dependencies"
|
||||
apt-get update && apt-get upgrade -y
|
||||
apt-get build-dep .
|
||||
echo -e "\e[0Ksection_end:`date +%s`:apt_get\r\e[0K"
|
||||
script:
|
||||
- |
|
||||
cd artifacts
|
||||
for FILE in *.*
|
||||
do
|
||||
echo "Calculating MD5 Hash for $FILE"
|
||||
md5sum $FILE > $FILE.md5
|
||||
done
|
||||
for FILE in rpm/*.rpm
|
||||
do
|
||||
echo "Calculating MD5 Hash for $FILE"
|
||||
md5sum $FILE > $FILE.md5
|
||||
done
|
||||
# This is for ARM 32 arch build
|
||||
test `node version.js` = `dpkg-parsechangelog -S version` || (echo "package.nw/package.json and debian/changelog version mismatch"; exit 1)
|
||||
echo -e "\e[0Ksection_start:`date +%s`:wget[collapsed=true]\r\e[0KGetting Upstream NWJS Binary"
|
||||
wget https://github.com/LeonardLaszlo/nw.js-armv7-binaries/releases/download/$NWJS32_BUILD/$NWJS32_BUILD.tar.gz
|
||||
tar -xf $NWJS32_BUILD.tar.gz
|
||||
tar -xf usr/docker/dist/nwjs-chromium-ffmpeg-branding/nwjs-$NWJS_VERSION-linux-arm.tar.gz
|
||||
echo -e "\e[0Ksection_end:`date +%s`:wget\r\e[0K"
|
||||
rm nwjs-$NWJS_VERSION-linux-arm/locales/*.info
|
||||
mv nwjs-$NWJS_VERSION-linux-arm/nw nwjs-$NWJS_VERSION-linux-arm/GridTracker
|
||||
version=`node ./version.js`
|
||||
mkdir GridTracker-$version-linux-arm32
|
||||
cp -r nwjs-$NWJS_VERSION-linux-arm/* GridTracker-$version-linux-arm32/
|
||||
cp -r arm/* GridTracker-$version-linux-arm32/
|
||||
cp -r package.nw GridTracker-$version-linux-arm32/
|
||||
cp LICENSE GridTracker-$version-linux-arm32/
|
||||
tar -czf GridTracker-$version-linux-arm32.tar.gz GridTracker-$version-linux-arm32
|
||||
mv GridTracker-$version-linux-arm32.tar.gz artifacts/
|
||||
# This is for ARM 64 arch build
|
||||
wget https://github.com/LeonardLaszlo/nw.js-armv7-binaries/releases/download/$NWJS64_BUILD/$NWJS64_BUILD.tar.gz
|
||||
tar -xf $NWJS64_BUILD.tar.gz
|
||||
tar -xf usr/docker/dist/nwjs-chromium-ffmpeg-branding/nwjs-$NWJS_VERSION-linux-arm64.tar.gz
|
||||
rm nwjs-$NWJS_VERSION-linux-arm64/locales/*.info
|
||||
mv nwjs-$NWJS_VERSION-linux-arm64/nw nwjs-$NWJS_VERSION-linux-arm64/GridTracker
|
||||
version=`node ./version.js`
|
||||
mkdir GridTracker-$version-linux-arm64
|
||||
cp -r nwjs-$NWJS_VERSION-linux-arm64/* GridTracker-$version-linux-arm64/
|
||||
cp -r arm/* GridTracker-$version-linux-arm64/
|
||||
cp -r package.nw GridTracker-$version-linux-arm64/
|
||||
cp LICENSE GridTracker-$version-linux-arm64/
|
||||
tar -czf GridTracker-$version-linux-arm64.tar.gz GridTracker-$version-linux-arm64
|
||||
mv GridTracker-$version-linux-arm64.tar.gz artifacts/
|
||||
echo "we made ARM packages!"
|
||||
ls -laR artifacts
|
||||
|
||||
ssh -o StrictHostKeyChecking=no gridtracker@$NR0Q_SERVER_ADDRESS "mkdir ~/$CI_COMMIT_TAG" && scp -o StrictHostKeyChecking=no -r ./* gridtracker@$NR0Q_SERVER_ADDRESS:~/$CI_COMMIT_TAG/ && ssh -o StrictHostKeyChecking=no gridtracker@$NR0Q_SERVER_ADDRESS "rm latest_test && ln -s $CI_COMMIT_TAG latest_test"
|
||||
|
||||
# copy release assets to NR0Q's server
|
||||
nr0q_upload_release:
|
||||
# copy test assets to Google Storage
|
||||
upload-Google:
|
||||
stage: deploy
|
||||
image: alpine
|
||||
image: google/cloud-sdk
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG =~ /^(v).*/ && $NR0Q_SERVER_KEY != ""'
|
||||
before_script:
|
||||
- |
|
||||
apk add openssh-client
|
||||
eval $(ssh-agent -s)
|
||||
echo "$NR0Q_SERVER_KEY" | tr -d '\r' | ssh-add -
|
||||
mkdir -p ~/.ssh; chmod 700 ~/.ssh
|
||||
- if: '$CI_COMMIT_TAG =~ /^(v|test_).*/'
|
||||
script:
|
||||
- |
|
||||
cd artifacts
|
||||
for FILE in *.*
|
||||
do
|
||||
echo "Calculating MD5 Hash for $FILE"
|
||||
md5sum $FILE > $FILE.md5
|
||||
done
|
||||
for FILE in rpm/*.rpm
|
||||
do
|
||||
echo "Calculating MD5 Hash for $FILE"
|
||||
md5sum $FILE > $FILE.md5
|
||||
done
|
||||
ssh -o StrictHostKeyChecking=no gridtracker@$NR0Q_SERVER_ADDRESS "mkdir ~/$CI_COMMIT_TAG" && scp -o StrictHostKeyChecking=no -r ./* gridtracker@$NR0Q_SERVER_ADDRESS:~/$CI_COMMIT_TAG/
|
||||
echo $GCP_SERVICE_KEY > gcloud-service-key.json
|
||||
gcloud auth activate-service-account --key-file gcloud-service-key.json
|
||||
gcloud config set project $GCLOUD_PROJECT_ID
|
||||
gsutil -m cp -R artifacts/* $GCLOUD_DEPLOY_PATH/
|
||||
|
||||
# this only creates a "source code release" -- gitlab doesn't specify binaries
|
||||
# except as links to external storage, which is suboptimal for now
|
||||
|
||||
source_release:
|
||||
sourcerelease:
|
||||
stage: deploy
|
||||
image: registry.gitlab.com/gitlab-org/release-cli:latest
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
rules:
|
||||
- if: '$CI_COMMIT_TAG =~ /^(v).*/'
|
||||
release:
|
||||
|
@ -320,8 +310,48 @@ source_release:
|
|||
assets:
|
||||
links:
|
||||
- name: Release Packages for $CI_COMMIT_TAG
|
||||
url: https://fleetwood.mchambersradio.com/gridtracker/$CI_COMMIT_TAG/
|
||||
url: https://https://storage.googleapis.com/gt_download/$CI_COMMIT_TAG/
|
||||
external: true
|
||||
link_type: package
|
||||
script:
|
||||
- echo 'Release for $CI_COMMIT_TAG'
|
||||
|
||||
update_arch_aur:
|
||||
stage: deploy
|
||||
image: archlinux:base-devel
|
||||
rules:
|
||||
# only do this with a manual tag starting with v
|
||||
- if: '$CI_COMMIT_TAG =~ /^v.*/ && $AUR_KEY != ""'
|
||||
before_script:
|
||||
- |
|
||||
pacman -Sy; pacman -S --needed --noconfirm openssh git
|
||||
eval $(ssh-agent -s)
|
||||
echo "$AUR_KEY" | tr -d '\r' | ssh-add -
|
||||
mkdir -p ~/.ssh; chmod 700 ~/.ssh
|
||||
git config --global user.name "nr0q"
|
||||
git config --global user.email "nr0q@gridtracker.org"
|
||||
script:
|
||||
# generate the PKGBUILD
|
||||
- |
|
||||
cd arch-linux
|
||||
curl -o gridtracker.tar.gz "https://gitlab.com/gridtracker.org/gridtracker/-/archive/${CI_COMMIT_TAG}/gridtracker-${CI_COMMIT_TAG}.tar.gz"
|
||||
SHASUM=$(sha256sum gridtracker.tar.gz | cut -d ' ' -f1)
|
||||
sed "s/REPLACE_WITH_VERSION/${CI_COMMIT_TAG#v}/;s/REPLACE_WITH_SHASUM/${SHASUM}/" PKGBUILD.template > PKGBUILD
|
||||
# test that it builds
|
||||
- |
|
||||
useradd builder -m
|
||||
passwd -d builder
|
||||
printf 'builder ALL=(ALL) ALL\n' | tee -a /etc/sudoers
|
||||
# build nwjs-bin
|
||||
sudo -u builder bash -c 'git clone https://aur.archlinux.org/nwjs-bin.git nwjs-bin && cd nwjs-bin && makepkg -si --noconfirm'
|
||||
# build gridtracker
|
||||
sudo -u builder makepkg -si --noconfirm PKGBUILD
|
||||
# push the new version
|
||||
- |
|
||||
sudo -u builder makepkg --printsrcinfo > .SRCINFO
|
||||
git clone ssh://aur@aur.archlinux.org/gridtracker.git
|
||||
cp PKGBUILD gridtracker/PKGBUILD
|
||||
cp .SRCINFO gridtracker/.SRCINFO
|
||||
cd gridtracker
|
||||
git add PKGBUILD .SRCINFO && git commit -m "upgpkg: gridtracker ${CI_COMMIT_TAG#v}" && git push
|
||||
|
||||
|
|
3
LICENSE
3
LICENSE
|
@ -1,6 +1,7 @@
|
|||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2018-2020 GridTricker.org
|
||||
Copyright (c) 2018-2020 Stephen Tag Loomis
|
||||
Copyright (c) 2018-2022 GridTricker.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
4
Makefile
4
Makefile
|
@ -21,6 +21,10 @@ clean:
|
|||
@echo "Cleaning $(DESTDIR)..."
|
||||
rm -rf $(DESTDIR)/*
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
@echo "GridTracker doesn't need building :D"
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
@echo "Installing gridtracker in $(DESTDIR)..."
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
NW.JS, the framekwork on which GridTracker is built is licensed uner the MIT licensed
|
||||
|
||||
Copyright (c) 2011-2019 NW.js Authors
|
||||
Copyright (c) 2011-2019 The Chromium Authors
|
||||
Copyright (c) 2011-2018 Intel Corp
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
||||
A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
34
README.md
34
README.md
|
@ -1,5 +1,15 @@
|
|||
# About GridTracker
|
||||
|
||||
GridTracker is designed for Amateur radio use. It's original tag-line was: "GridTracker listens to traffic from WSJT-X and displays it on a map. It will also load ADIF log files".
|
||||
This was back in February of 2018. At its core GridTracker has remained true to that description but it has evolved to be a very powerful amateur radio tool and not just for FT8.
|
||||
GridTracker is a warehouse of amateur radio information presented in an easy to use interface, from live traffic decodes, logbooks, spot reports, weather, current solar conditions and more.
|
||||
[Read more](https://gitlab.com/gridtracker.org/gridtracker/-/wikis/Introduction/What-is-GridTracker)
|
||||
|
||||
See the [Wiki](https://gitlab.com/gridtracker.org/gridtracker/-/wikis/home) for the user documentation.
|
||||
|
||||
# Getting GridTracker
|
||||
GridTracker can be downloaded for nearly all common platforms (Windows, MacOS, Linux, Raspberry Pi) from the [downloads](https://gridtracker.org/downloads/) page on our website GridTracker.org.
|
||||
|
||||
# Developing GridTracker
|
||||
|
||||
GridTracker runs using [NWJS](https://nwjs.io/), a tools that wraps both Chrome windows and node processes into
|
||||
|
@ -21,10 +31,18 @@ automatically, but if you want to run on the command line, you can (after runnin
|
|||
|
||||
# Developer Environment Setup
|
||||
|
||||
Our builds and development environment are usually managed by [nwjs-builder-phoenix](https://github.com/evshiron/nwjs-builder-phoenix), but it only supports Intel-based architectures.
|
||||
|
||||
## x86-based Windows, Mac, Linux
|
||||
|
||||
Run `npm install` and then `npm start`
|
||||
|
||||
## Apple Silicon Macs (M1, M1 Pro, M1 Max)
|
||||
|
||||
Phoenix does not support ARM-based macs, so we have to explicitly tell it to use Intel-based versions of NWJS.
|
||||
|
||||
Run `npm install` and then `npm run start-x64`
|
||||
|
||||
## ARM-based Raspberry
|
||||
|
||||
Run `npm install`.
|
||||
|
@ -89,3 +107,19 @@ Final build results are left in:
|
|||
# Editing GeoJSON files
|
||||
|
||||
We've had success using https://vector.rocks/ and then cleaning up the output with https://jsonformatter.org/
|
||||
|
||||
# Hacks
|
||||
|
||||
### Roster Column Ordering
|
||||
|
||||
We've added internal support for reordering roster columns, but have yet to implement a UI to change these settings.
|
||||
|
||||
In the meantime you can:
|
||||
* Open the roster window, right click on the "More Controls" link on the top right corner and select "Inspect" from the context menu.
|
||||
|
||||
* Select the "Console" tab in the Chrome DevTools window that should have appeared.
|
||||
|
||||
* Enter `g_rosterSettings.columnOrder` in the Console and press `[return]` to see the current list of columns.
|
||||
|
||||
* Enter the following in the Console, changing the values of `columnOrder` to fit your needs: `changeRosterColumnOrder(["Callsign", "Grid", "Spot"]);` and press `[return]`.
|
||||
Any columns included in this list will be shown before all other columns.
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
# Maintainer: nr0q <nr0q@gridtracker.org>
|
||||
# Contributor: classabbyamp <dev@kb6.ee>
|
||||
|
||||
pkgname=gridtracker
|
||||
pkgver=REPLACE_WITH_VERSION
|
||||
pkgrel=1
|
||||
pkgdesc="Companion program for WSJT-X for mapping contacts"
|
||||
arch=('x86_64')
|
||||
url="https://gridtracker.org/grid-tracker/"
|
||||
license=('BSD')
|
||||
depends=('nwjs-bin>=0.54.0')
|
||||
replaces=('gridtracker-bin')
|
||||
source=("https://gitlab.com/gridtracker.org/$pkgname/-/archive/v$pkgver/$pkgname-v$pkgver.tar.gz")
|
||||
sha256sums=('REPLACE_WITH_SHASUM')
|
||||
|
||||
package() {
|
||||
cd "$srcdir/$pkgname-v$pkgver/"
|
||||
make install DESTDIR=$pkgdir NO_DIST_INSTALL=true
|
||||
}
|
|
@ -1,10 +1,61 @@
|
|||
gridtracker (1.22.0503) unstable; urgency=low
|
||||
- Increment version for build with correct NWJS version
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Mon, 01 May 2022 16:07:00 -0000
|
||||
|
||||
gridtracker (1.22.0502) unstable; urgency=low
|
||||
[Bug Fixes]
|
||||
- Fixed broken Call Roster due to online assets being moved from a web server to Google Storage Bucket.
|
||||
- Don't highlight "CQ" rows if filtering by "CQ Only".
|
||||
- Resolved #126 Windows Installer script updated to fix issues with install location and missing registry keys
|
||||
- Resolved #124 removing IP-Geolocation when no all other means of locating failed, we now tell the user to
|
||||
start WSJT-X or enter a location as Geo-Location services are costly and unreliable
|
||||
- Resolved #137 missing libatomic dependency in Linux DEB and RPM spec files
|
||||
[Enhancements]
|
||||
- Include version number in main window title
|
||||
- Call Roster colums refactored and wanted column added
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Mon, 01 May 2022 02:25:40 -0000
|
||||
|
||||
gridtracker (1.21.1217) unstable; urgency=low
|
||||
- Changed to newer NWJS to fix upstream bug that caused media playback to fail.
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Fri, 17 Dec 2021 20:08:00 -0000
|
||||
|
||||
gridtracker (1.21.1212) unstable; urgency=low
|
||||
Release build with the call roster refactor code that's been in the works for some time.
|
||||
[Bug Fixes]
|
||||
- Fix #76, unfinished ignore CQ and ITU zones.
|
||||
- Improved handling of stations that are not in a valid DXCC (ie; /MM stations)
|
||||
- Improved handling of free text decodes that don't contain valid callsigns (ie "HI BOB" and "MERRY XMAS")
|
||||
- Fix how the Call Roster title bar counts are calculated.
|
||||
[Enhancements]
|
||||
- More clarity when a ULS Zip code falls in more then one county, replacing ~ with ? symbols and
|
||||
better tool tip message.
|
||||
- Fix #107, where the call roster timeout was longer then a single FT4 cycle.
|
||||
- Fix #91, CQ is always highlighted, no matter status of CQ Only.
|
||||
- Performance improvement by changing how call roster vars are handled ('let' vs 'var')
|
||||
- Build system improved to push to Arch AUR, building of Debian (.deb) packages and triggering
|
||||
of COPR RPM builds for Fedora/Cent/RHEL and their cousins.
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Thu, 12 Dec 2021 15:10:00 -0000
|
||||
|
||||
gridtracker (1.21.0928) unstable; urgency=medium
|
||||
[Bug Fixes]
|
||||
- Treat ADIF record values as byte length vs string length (to better handle UTSF-8 data).
|
||||
- Remove looking at fetched records for last date for LoTW fetches, Use only headers (More reliable LoTW fetches).
|
||||
[Enhancements]
|
||||
- ARM builds now with NWJS 0.54.2 and 64 bit ARM binaries.
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Sun, 28 Sep 2021 00:00:00 -0000
|
||||
|
||||
gridtracker (1.21.0620) unstable; urgency=medium
|
||||
[Bug Fixes]
|
||||
- Fix pulling down of LoTW logs at start-up with a differential log syncing mechanism that only get's changes since last sync, also cool down timer to prevent rapid reloading of LoTW log.
|
||||
[Enhancements]
|
||||
- Automatic pulling down of acknowledgements.json file daily when doing version check (if enabled).
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Sat, 19 June 20201 16:49:00 -0000
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Sat, 19 Jun 2021 16:49:00 -0000
|
||||
|
||||
gridtracker (1.21.0613) unstable; urgency=medium
|
||||
[Bug Fixes]
|
||||
|
@ -12,7 +63,7 @@ gridtracker (1.21.0613) unstable; urgency=medium
|
|||
[Enhancements]
|
||||
- Updated list of contributors
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Sun, 13 June 2021 03:04:00 -0000
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Sun, 13 Jun 2021 03:04:00 -0000
|
||||
|
||||
gridtracker (1.21.0530) unstable; urgency=medium
|
||||
[Bug Fixes]
|
||||
|
@ -25,7 +76,7 @@ gridtracker (1.21.0530) unstable; urgency=medium
|
|||
[Enhancements]
|
||||
- Add statistical information to call roster title bar
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Sat, 30 May 2021 00:10:00 -0000
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Sat, 30 May 2021 00:10:00 -0000
|
||||
|
||||
gridtracker (1.21.0520) unstable; urgency=medium
|
||||
[Bug Fixes]
|
||||
|
@ -41,7 +92,7 @@ gridtracker (1.21.0520) unstable; urgency=medium
|
|||
- Make settings icon a toggle that both opens and closes the settings pane
|
||||
- Grid and IP Address Fields are slightly wider
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Mon, 17 May 2021 02:30:00 -0000
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Mon, 17 May 2021 02:30:00 -0000
|
||||
|
||||
gridtracker (1.21.0407) unstable; urgency=medium
|
||||
[Bug Fixes]
|
||||
|
@ -52,12 +103,12 @@ gridtracker (1.21.0407) unstable; urgency=medium
|
|||
- new icon to request ClubLog OQRS QSL
|
||||
- add eQSL check in log file processing
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Wed, 07 Apr 2021 00:00:00 -0000
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Wed, 07 Apr 2021 00:00:00 -0000
|
||||
|
||||
gridtracker (1.21.0327) unstable; urgency=medium
|
||||
This is the public release of the 1.21.0324 hotfix release candidates
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Fri, 27 Mar 2021 00:38:00 -0000
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Fri, 27 Mar 2021 00:38:00 -0000
|
||||
|
||||
gridtracker (1.21.0324) unstable; urgency=medium
|
||||
[Christian Bayer]
|
||||
|
@ -104,6 +155,8 @@ gridtracker (1.21.0307) unstable; urgency=medium
|
|||
queried from Callook since it usually has more data than free QRZ lookup
|
||||
* fixed CR alert script not being triggered for Awared Tracker hits
|
||||
|
||||
-- Matthew Chambers <nr0q@gridtracker.org> Sun, 7 Mar 2021 12:00:00 -0000
|
||||
|
||||
gridtracker (1.20.1118) unstable; urgency=low
|
||||
|
||||
* GridTracker is now Open Source! Copyright assigned to GridTracker.org and
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
Source: gridtracker
|
||||
Section: hamradio
|
||||
Priority: optional
|
||||
Maintainer: Paul Traina <216482-pleasantone@users.noreply.gitlab.com>
|
||||
Maintainer: Matthew Chambers <nr0q@gridtracker.org>
|
||||
Build-Depends: debhelper (>= 12.1)
|
||||
Standards-Version: 4.3.0
|
||||
Homepage: http://gridtracker.org/
|
||||
Homepage: https://gridtracker.org/
|
||||
|
||||
Package: gridtracker
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}
|
||||
Architecture: all
|
||||
Depends: ${misc:Depends} nwjs
|
||||
Recommends: speech-dispatcher-espeak-ng
|
||||
Description: Companion program to WSJT-X/JTDX
|
||||
.
|
||||
|
|
|
@ -4,9 +4,9 @@ Upstream-Contact: GridTracker Team <contact@gridtracker.org>
|
|||
Source: https://gitlab.com/gridtracker.org/gridtracker
|
||||
|
||||
Files: *
|
||||
Copyright: Copyright (c) 2018-2020 by Tag Loomis, 2020 by GridTracker.org
|
||||
Copyright: Copyright (c) 2018-2020 by Tag Loomis, 2020-2022 by GridTracker.org
|
||||
License: BSD-3-clause
|
||||
Copyright (c) 2018-2020 GridTricker.org
|
||||
Copyright (c) 2018-2022 GridTricker.org
|
||||
All rights reserved.
|
||||
.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#!/usr/bin/make -f
|
||||
export NO_DIST_INSTALL = true
|
||||
export DH_VERBOSE = 1
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
|
|
@ -15,26 +15,18 @@ for dir in dist/*-linux-* ; do
|
|||
fi
|
||||
done
|
||||
for dir in dist/*-win-* ; do
|
||||
if [ -d $dir ] ; then
|
||||
mkdir $dir/package.nw
|
||||
for file in package.nw/* ; do
|
||||
mv $dir/`basename $file` $dir/package.nw
|
||||
done
|
||||
elif [ -f $dir ] && [[ "$dir" == *"win-x86-Setup.exe"* ]] ; then
|
||||
if [ -f $dir ] && [[ "$dir" == *"-Setup.exe" ]] ; then
|
||||
echo "deleting broken installer $dir"
|
||||
rm $dir
|
||||
fi
|
||||
done
|
||||
|
||||
sed "s#GridTracker-\${VERSION}-win-x86/#`pwd`/dist/GridTracker-\${VERSION}-win-x86/#g" windows/setup.nsi.tmpl > windows/setup.nsi.tmp.1
|
||||
sed "s#GridTracker-Installer.#`pwd`/dist/GridTracker-Installer.#g" windows/setup.nsi.tmp.1 > windows/setup.nsi.tmp.2
|
||||
sed "s#define VERSION <placeholder#define VERSION `node version.js`#g" windows/setup.nsi.tmp.2 > windows/setup.nsi
|
||||
|
||||
sed "s#<versionplaceholder>#`node version.js`#g" windows/win_installer.nsi > windows/setup.nsi.tmp.1
|
||||
sed "s#<buildplaceholder>#`pwd`#g" windows/setup.nsi.tmp.1 > windows/setup.nsi
|
||||
makensis windows/setup.nsi
|
||||
# clean up generated files
|
||||
rm windows/setup.nsi
|
||||
rm windows/setup.nsi.tmp.1
|
||||
rm windows/setup.nsi.tmp.2
|
||||
|
||||
mv dist/*{.exe,mac-x64.zip,.tar.gz} ../dist
|
||||
rpmbuild -D "version `node ./version.js`" --build-in-place -bb gridtracker.i386.spec
|
||||
|
|
|
@ -43,7 +43,7 @@ Run gridtracker, no arguments needed.
|
|||
.SH COPYRIGHT
|
||||
.PP
|
||||
Copyright (c) 2018-2020 Stephen Tag Loomis. All rights reserved.
|
||||
Copyright (c) 2020 GridTracker.org. All rights reserved.
|
||||
Copyright (c) 2020-2022 GridTracker.org. All rights reserved.
|
||||
Released under BSD 3-Clause License
|
||||
https://gridtracker.org
|
||||
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
# Build with the following syntax:
|
||||
#
|
||||
# version=`node ./version.js`
|
||||
# rpmbuild -D "version ${version}" --build-in-place -bb --target i386 gridtracker.i386.spec
|
||||
|
||||
Name: gridtracker
|
||||
Summary: GridTracker: An amateur radio companion to WSJT-X or JTDX
|
||||
Version: %{version}
|
||||
Release: 1%{?dist}
|
||||
BuildArch: armv7
|
||||
Source0: GridTracker-%{version}-linux-arm.tar.gz
|
||||
|
||||
License: BSD 3-Clause License
|
||||
URL: https://gridtracker.org
|
||||
Group: Science & Math
|
||||
Packager: Matthew Chambers <nr0q@gridtracker.org>
|
||||
# Requires: nwjs
|
||||
# BuildRequires: desktop-file-utils
|
||||
|
||||
%description
|
||||
GridTracker listens to traffic from WSJT-X/JTDX, displays it on a map,
|
||||
and has a sophisticated alerting and filtering system for finding and
|
||||
working interesting stations. It also will upload QSO records to multiple
|
||||
logging frameworks including Logbook of the World.
|
||||
|
||||
%prep
|
||||
%setup -n GridTracker
|
||||
|
||||
#%build
|
||||
|
||||
|
||||
%install
|
||||
mkdir -p ${RPM_BUILD_ROOT}/usr/share/%{name}
|
||||
cp -aR GridTracker-%version-linux-arm/ ${RPM_BUILD_ROOT}/usr/share/%{name}/
|
||||
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man1
|
||||
cp -a %{name}.1 ${RPM_BUILD_ROOT}%{_mandir}/man1/
|
||||
mkdir -p ${RPM_BUILD_ROOT}%{_docdir}/%{name}
|
||||
cp -a LICENSE ${RPM_BUILD_ROOT}%{_docdir}/%{name}/
|
||||
mkdir -p ${RPM_BUILD_ROOT}/usr/share/applications
|
||||
cat > ${RPM_BUILD_ROOT}/usr/share/applications/%{name}.desktop << 'EOF'
|
||||
[Desktop Entry]
|
||||
Name=GridTracker
|
||||
Comment=GridTracker
|
||||
Exec=/usr/share/%{name}/GridTracker
|
||||
Icon=/usr/share/%{name}/gridtracker.png
|
||||
Path=/usr/share/%{name}
|
||||
Type=Application
|
||||
Encoding=UTF-8
|
||||
Terminal=false
|
||||
Categories=DataVisualization,Geography,Education;
|
||||
EOF
|
||||
|
||||
chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/; chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/GridTracker; chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/lib; chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/locales
|
||||
find ${RPM_BUILD_ROOT}/usr/share/ -type f \( -name '*.so' -o -name '*.so.*' \) -exec chmod 755 {} +
|
||||
|
||||
# %check
|
||||
|
||||
# %clean
|
||||
|
||||
%files
|
||||
/usr/share/%{name}/
|
||||
/usr/share/applications/%{name}.desktop
|
||||
%{_datadir}/%{name}/
|
||||
%{_mandir}/man1/
|
||||
%license %{_docdir}/%{name}/
|
|
@ -1,65 +0,0 @@
|
|||
# Build with the following syntax:
|
||||
#
|
||||
# version=`node ./version.js`
|
||||
# rpmbuild -D "version ${version}" --build-in-place -bb --target i386 gridtracker.i386.spec
|
||||
|
||||
Name: gridtracker
|
||||
Summary: GridTracker: An amateur radio companion to WSJT-X or JTDX
|
||||
Version: %{version}
|
||||
Release: 1%{?dist}
|
||||
BuildArch: i386
|
||||
Source0: GridTracker-%{version}-linux-x86.tar.gz
|
||||
|
||||
License: BSD 3-Clause License
|
||||
URL: https://gridtracker.org
|
||||
Group: Science & Math
|
||||
Packager: Matthew Chambers <nr0q@gridtracker.org>
|
||||
# Requires: nwjs
|
||||
# BuildRequires: desktop-file-utils
|
||||
|
||||
%description
|
||||
GridTracker listens to traffic from WSJT-X/JTDX, displays it on a map,
|
||||
and has a sophisticated alerting and filtering system for finding and
|
||||
working interesting stations. It also will upload QSO records to multiple
|
||||
logging frameworks including Logbook of the World.
|
||||
|
||||
%prep
|
||||
%setup -n GridTracker
|
||||
|
||||
#%build
|
||||
|
||||
|
||||
%install
|
||||
mkdir -p ${RPM_BUILD_ROOT}/usr/share/%{name}
|
||||
cp -aR dist/*-linux-x86/* ${RPM_BUILD_ROOT}/usr/share/%{name}/
|
||||
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man1
|
||||
cp -a %{name}.1 ${RPM_BUILD_ROOT}%{_mandir}/man1/
|
||||
mkdir -p ${RPM_BUILD_ROOT}%{_docdir}/%{name}
|
||||
cp -a LICENSE ${RPM_BUILD_ROOT}%{_docdir}/%{name}/
|
||||
mkdir -p ${RPM_BUILD_ROOT}/usr/share/applications
|
||||
cat > ${RPM_BUILD_ROOT}/usr/share/applications/%{name}.desktop << 'EOF'
|
||||
[Desktop Entry]
|
||||
Name=GridTracker
|
||||
Comment=GridTracker
|
||||
Exec=/usr/share/%{name}/GridTracker
|
||||
Icon=/usr/share/%{name}/gridtracker.png
|
||||
Path=/usr/share/%{name}
|
||||
Type=Application
|
||||
Encoding=UTF-8
|
||||
Terminal=false
|
||||
Categories=DataVisualization,Geography,Education;
|
||||
EOF
|
||||
|
||||
chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/; chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/GridTracker; chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/lib; chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/locales
|
||||
find ${RPM_BUILD_ROOT}/usr/share/ -type f \( -name '*.so' -o -name '*.so.*' \) -exec chmod 755 {} +
|
||||
|
||||
# %check
|
||||
|
||||
# %clean
|
||||
|
||||
%files
|
||||
/usr/share/%{name}/
|
||||
/usr/share/applications/%{name}.desktop
|
||||
%{_datadir}/%{name}/
|
||||
%{_mandir}/man1/
|
||||
%license %{_docdir}/%{name}/
|
|
@ -0,0 +1,73 @@
|
|||
Name: {{{ git_name name=gridtracker }}}
|
||||
Summary: GridTracker: An amateur radio companion to WSJT-X or JTDX
|
||||
Version: {{{ git_version lead=1.22.0503 }}}
|
||||
Release: 1%{?dist}
|
||||
BuildArch: noarch
|
||||
Source0: {{{ git_dir_pack }}}
|
||||
|
||||
License: BSD 3-Clause License
|
||||
URL: https://gridtracker.org
|
||||
Group: Science & Math
|
||||
Packager: Matthew Chambers <nr0q@gridtracker.org>
|
||||
Requires: nwjs
|
||||
BuildRequires: desktop-file-utils make nodejs
|
||||
|
||||
%description
|
||||
GridTracker listens to traffic from WSJT-X/JTDX, displays it on a map,
|
||||
and has a sophisticated alerting and filtering system for finding and
|
||||
working interesting stations. It also will upload QSO records to multiple
|
||||
logging frameworks including Logbook of the World.
|
||||
|
||||
%prep
|
||||
{{{ git_dir_setup_macro }}}
|
||||
|
||||
%build
|
||||
|
||||
%install
|
||||
DESTDIR=${RPM_BUILD_ROOT} make NO_DIST_INSTALL=true install
|
||||
|
||||
%check
|
||||
|
||||
%clean
|
||||
DESTDIR=${RPM_BUILD_ROOT} make clean
|
||||
|
||||
%files
|
||||
%{_datadir}/%{name}/
|
||||
%{_datadir}/applications/%{name}.desktop
|
||||
%{_datadir}/%{name}/
|
||||
%{_bindir}/%{name}
|
||||
%{_mandir}/man1/
|
||||
%license %{_docdir}/%{name}/
|
||||
|
||||
%changelog
|
||||
* Mon May 02 2022 Matthew Chambers <nr0q@gridtracker.org> - 1.22.0503-1
|
||||
- Increment version number for build with correct vesion of NWJS
|
||||
* Mon May 02 2022 Matthew Chambers <nr0q@gridtracker.org> - 1.22.0502-1
|
||||
- [Bug Fixes]
|
||||
- Fixed broken Call Roster due to online assets being moved from a web server to Google Storage Bucket.
|
||||
- Don't highlight "CQ" rows if filtering by "CQ Only".
|
||||
- Resolved #126 Windows Installer script updated to fix issues with install location and missing registry keys
|
||||
- Resolved #124 removing IP-Geolocation when no all other means of locating failed, we now tell the user to
|
||||
start WSJT-X or enter a location as Geo-Location services are costly and unreliable
|
||||
- Resolved #137 missing libatomic dependency in Linux DEB and RPM spec files
|
||||
- [Enhancements]
|
||||
- Include version number in main window title
|
||||
- Call Roster colums refactored and wanted column added
|
||||
* Fri Dec 17 2021 Matthew Chambers <nr0q@gridtracker.org> - 1.21.1217-1
|
||||
- Changed to newer NWJS to fix upstream bug that caused media playback to fail.
|
||||
* Sun Dec 12 2021 Matthew Chambers <nr0q@gridtracker.org> - 1.21.1212-1
|
||||
- Release build with the call roster refactor code that's been in the works for some time.
|
||||
- [Bug Fixes]
|
||||
- Fix #76, unfinished ignore CQ and ITU zones.
|
||||
- Improved handling of stations that are not in a valid DXCC (ie; /MM stations)
|
||||
- Improved handling of free text decodes that don't contain valid callsigns (ie "HI BOB" and "MERRY XMAS")
|
||||
- Fix how the Call Roster title bar counts are calculated.
|
||||
- [Enhancements]
|
||||
- More clarity when a ULS Zip code falls in more then one county, replacing ~ with ? symbols and better tool tip message.
|
||||
- Fix #107, where the call roster timeout was longer then a single FT4 cycle.
|
||||
- Fix #91, CQ is always highlighted, no matter status of CQ Only.
|
||||
- Performance improvement by changing how call roster vars are handled ('let' vs 'var')
|
||||
- Build system improved to push to Arch AUR, building of Debian (.deb) packages and triggering
|
||||
of COPR RPM builds for Fedora/Cent/RHEL and their cousins.
|
||||
* Thu Sep 30 2021 Matthew Chambers <nr0q@gridtracker.org> - 1.21.0928-1
|
||||
- First attempt at repo grade RPM builds
|
|
@ -1,66 +0,0 @@
|
|||
# Build with the following syntax:
|
||||
#
|
||||
# version=`node ./version.js`
|
||||
# rpmbuild -D "version ${version}" --build-in-place -bb --target x86_64 gridtracker.x86_64.spec
|
||||
|
||||
Name: gridtracker
|
||||
Summary: GridTracker: An amateur radio companion to WSJT-X or JTDX
|
||||
Version: %{version}
|
||||
Release: 1%{?dist}
|
||||
BuildArch: x86_64
|
||||
Source0: GridTracker-%{version}-linux-x64.tar.bz
|
||||
|
||||
License: BSD 3-Clause License
|
||||
URL: https://gridtracker.org
|
||||
Group: Science & Math
|
||||
Packager: Matthew Chambers
|
||||
# Requires: nwjs
|
||||
# BuildRequires: desktop-file-utils
|
||||
|
||||
%description
|
||||
GridTracker listens to traffic from WSJT-X/JTDX, displays it on a map,
|
||||
and has a sophisticated alerting and filtering system for finding and
|
||||
working interesting stations. It also will upload QSO records to multiple
|
||||
logging frameworks including Logbook of the World.
|
||||
|
||||
|
||||
%prep
|
||||
%setup -n GridTracker
|
||||
|
||||
%build
|
||||
|
||||
|
||||
%install
|
||||
mkdir -p ${RPM_BUILD_ROOT}/usr/share/%{name}
|
||||
cp -aR dist/*-linux-x64/* ${RPM_BUILD_ROOT}/usr/share/%{name}/
|
||||
mkdir -p ${RPM_BUILD_ROOT}%{_mandir}/man1
|
||||
cp -a %{name}.1 ${RPM_BUILD_ROOT}%{_mandir}/man1/
|
||||
mkdir -p ${RPM_BUILD_ROOT}%{_docdir}/%{name}
|
||||
cp -a LICENSE ${RPM_BUILD_ROOT}%{_docdir}/%{name}/
|
||||
mkdir -p ${RPM_BUILD_ROOT}/usr/share/applications
|
||||
cat > ${RPM_BUILD_ROOT}/usr/share/applications/%{name}.desktop << 'EOF'
|
||||
[Desktop Entry]
|
||||
Name=GridTracker
|
||||
Comment=GridTracker
|
||||
Exec=/usr/share/%{name}/GridTracker
|
||||
Icon=/usr/share/%{name}/gridtracker.png
|
||||
Path=/usr/share/%{name}
|
||||
Type=Application
|
||||
Encoding=UTF-8
|
||||
Terminal=false
|
||||
Categories=DataVisualization,Geography,Education;
|
||||
EOF
|
||||
|
||||
chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/; chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/GridTracker; chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/lib; chmod 755 ${RPM_BUILD_ROOT}/usr/share/%{name}/locales
|
||||
find ${RPM_BUILD_ROOT}/usr/share/ -type f \( -name '*.so' -o -name '*.so.*' \) -exec chmod 755 {} +
|
||||
|
||||
# %check
|
||||
|
||||
# %clean
|
||||
|
||||
%files
|
||||
/usr/share/%{name}/
|
||||
/usr/share/applications/%{name}.desktop
|
||||
%{_datadir}/%{name}/
|
||||
%{_mandir}/man1/
|
||||
%license %{_docdir}/%{name}/
|
Plik diff jest za duży
Load Diff
|
@ -13,12 +13,11 @@
|
|||
"test": "eslint package.nw",
|
||||
"lint-check": "eslint package.nw",
|
||||
"lint-fix": "eslint --fix package.nw",
|
||||
"dist-nix": "build --concurrent --tasks linux-x86,linux-x64,mac-x64 package.nw",
|
||||
"dist-nix": "build --concurrent --tasks linux-x86,linux-x64 package.nw",
|
||||
"dist-mac": "build --concurrent --tasks mac-x64 package.nw",
|
||||
"dist-win": "build --concurrent --tasks win-x86,win-x64 package.nw",
|
||||
"distsome": "build --debug --tasks linux-x64,mac-x64 package.nw",
|
||||
"start": "run package.nw"
|
||||
},
|
||||
"dependencies": {
|
||||
"discord-urpc": "^1.0.1"
|
||||
"start": "run package.nw",
|
||||
"start-x64": "run --x64 package.nw"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<!--
|
||||
GridTracker Copyright © 2018-2021 GridTracker.org
|
||||
GridTracker Copyright © 2018-2022 GridTracker.org
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
@ -756,6 +756,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
id="myTooltip"
|
||||
style="
|
||||
-webkit-user-select: text;
|
||||
user-select: text;
|
||||
background-color: black;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
|
@ -1071,7 +1072,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
<br />
|
||||
<div
|
||||
class="button"
|
||||
onclick="require('nw.gui').Shell.openExternal('http://app.gridtracker.org/gt_print.html');"
|
||||
onclick="require('nw.gui').Shell.openExternal('https://storage.googleapis.com/gt_app/gt_print.html');"
|
||||
>
|
||||
Print
|
||||
</div>
|
||||
|
@ -2893,7 +2894,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
<td colspan="2">
|
||||
<input
|
||||
type="range"
|
||||
min="15"
|
||||
min="5"
|
||||
max="300"
|
||||
value="120"
|
||||
step="15"
|
||||
|
@ -2905,6 +2906,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="mapItem">
|
||||
<table align="center">
|
||||
<tr align="center">
|
||||
<td align="center">Clear Call Roster on Band change</td>
|
||||
</tr>
|
||||
<tr align="center">
|
||||
<td colspan="2">
|
||||
<input type="checkbox" id="clearRosterOnBandChange" onchange="clearRosterOnBandChangeValueChanged(this);" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<br />
|
||||
<div class="mapItem" id="haltTXDiv" style="display: none">
|
||||
<table align="center">
|
||||
|
@ -3526,7 +3539,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
>GridTracker.org!</a
|
||||
>
|
||||
</p>
|
||||
<p>Copyright © 2021 GridTracker.org</p>
|
||||
<p>Copyright © 2022 GridTracker.org</p>
|
||||
<img src="./gridview.png" /> <br />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3623,6 +3636,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
<h2>GridTracker is up to date!</h2>
|
||||
<div class="button" onclick="closeUpdateToDateDiv();">OK</div>
|
||||
</div>
|
||||
<div id="selectNodeDiv" style="-webkit-user-select: text; display: block; z-index: -10000"></div>
|
||||
<div id="selectNodeDiv" style="-webkit-user-select: text; user-select: text; display: block; z-index: -10000"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -1,72 +1,20 @@
|
|||
{
|
||||
"A41MK": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"AA5KD": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"AD0WB": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"AE4ON": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"AF2V": {
|
||||
"badge": "img/emojis/books.png",
|
||||
"message": "GridTracker Documentation"
|
||||
},
|
||||
"AJ6RX": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"BD3OOX": {
|
||||
"badge": "img/emojis/speech.png",
|
||||
"message": "GridTracker Translator"
|
||||
},
|
||||
"CX4CD": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"DE1JPJ": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"DL6RA": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"EI8GS": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"GI1MIC": {
|
||||
"badge": "img/emojis/pizza.png",
|
||||
"message": "GridTracker Tester"
|
||||
},
|
||||
"GM4SJB": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"HB9VKL": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"HI80": {
|
||||
"badge": "img/emojis/speech.png",
|
||||
"message": "GridTracker Translator"
|
||||
},
|
||||
"I4SOI": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"IW2BUW": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"IW3HMH": {
|
||||
"badge": "img/emojis/logbook.png",
|
||||
"message": "Creator of Log4OM"
|
||||
|
@ -79,98 +27,30 @@
|
|||
"badge": "img/emojis/star.png",
|
||||
"message": "Creator of FT8 and WSJT-X"
|
||||
},
|
||||
"K2PF": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"K4TLS": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"K5DCC": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"K5TUX": {
|
||||
"badge": "img/emojis/penguin.png",
|
||||
"message": "GridTracker Partner"
|
||||
},
|
||||
"K7CGA": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"K7YD": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"K8VSY": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"K9AN": {
|
||||
"badge": "img/emojis/star.png",
|
||||
"message": "Co-Creator of FT8"
|
||||
},
|
||||
"K9MIH": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KA0AZS": {
|
||||
"badge": "img/emojis/pizza.png",
|
||||
"message": "GridTracker Tester"
|
||||
},
|
||||
"KA4JON": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KA7JAZ": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KB2BK": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KB2YSI": {
|
||||
"badge": "img/emojis/coffee.png",
|
||||
"message": "GridTracker Developer"
|
||||
},
|
||||
"KB4RSM": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KB5ITC": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KC4HN": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KC7ZXY": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KD0YTE": {
|
||||
"badge": "img/emojis/pizza.png",
|
||||
"message": "GridTracker Tester"
|
||||
},
|
||||
"KD9QGP": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KE0UL": {
|
||||
"badge": "img/emojis/grandfather.png",
|
||||
"message": "GridTracker's Grandfather"
|
||||
},
|
||||
"KE1Q": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KE4WLE": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KF5QHQ": {
|
||||
"badge": "img/emojis/trophy.png",
|
||||
"message": "GridTracker Developer"
|
||||
|
@ -179,34 +59,6 @@
|
|||
"badge": "img/emojis/flatbread.png",
|
||||
"message": "GridTracker Developer"
|
||||
},
|
||||
"KJ7KRN": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KO4BCN": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KQ4Y": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"KW4AU": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"LA6YJA": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"LU7DK": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"N0GTO": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"N0TTL": {
|
||||
"badge": "img/emojis/star.png",
|
||||
"message": "Creator of GridTracker"
|
||||
|
@ -219,78 +71,10 @@
|
|||
"badge": "img/emojis/books.png",
|
||||
"message": "GridTracker Documentation"
|
||||
},
|
||||
"N3TQM": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"N3UGI": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"N4MCC": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"N6GEB": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"N7HQ": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"NR0Q": {
|
||||
"badge": "img/emojis/coffee.png",
|
||||
"message": "GridTracker Developer"
|
||||
},
|
||||
"OH1LEU": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"OH3NZW": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"ON7IVE": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"OZ1LNR": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"OZ8QI": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"PA0LMA": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"VA7CND": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"VE3FMQ": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"VE7LGP": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"W0SP": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"W0YRE": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"W4DHK": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"W4IPA": {
|
||||
"badge": "img/emojis/beer-mug.png",
|
||||
"message": "GridTracker Tester"
|
||||
|
@ -299,36 +83,8 @@
|
|||
"badge": "img/emojis/pizza.png",
|
||||
"message": "GridTracker Tester"
|
||||
},
|
||||
"W6FVO": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"W9LL": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"W9VZR": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"WA4YA": {
|
||||
"badge": "img/emojis/trophy.png",
|
||||
"message": "GridTracker Developer"
|
||||
},
|
||||
"WA6JQB": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"WB6RJH": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"WD5FBW": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
},
|
||||
"WS4S": {
|
||||
"badge": "img/emojis/money-bag.png",
|
||||
"message": "GridTracker Donor"
|
||||
}
|
||||
}
|
|
@ -31878,6 +31878,7 @@
|
|||
"=NH6MG",
|
||||
"=NH6NG",
|
||||
"=NH6NS",
|
||||
"=NH6PK",
|
||||
"=NH6QR",
|
||||
"=NH6R",
|
||||
"=NH6RG",
|
||||
|
@ -43922,6 +43923,31 @@
|
|||
"worked_modes": {},
|
||||
"confirmed_modes": {}
|
||||
},
|
||||
"390": {
|
||||
"dxcc": "0",
|
||||
"cc": "-",
|
||||
"ccc": "-",
|
||||
"name": "None",
|
||||
"continent": "-",
|
||||
"ituzone": ["-"],
|
||||
"cqzone": ["-"],
|
||||
"timezone": "1",
|
||||
"ccode": "-",
|
||||
"aname": "None",
|
||||
"mh": [],
|
||||
"prefix": [],
|
||||
"worked": false,
|
||||
"confirmed": false,
|
||||
"flag": "un.png",
|
||||
"pp": "-",
|
||||
"lat": 0.0,
|
||||
"lon": 0.0,
|
||||
"geo": "deleted",
|
||||
"worked_bands": {},
|
||||
"confirmed_bands": {},
|
||||
"worked_modes": {},
|
||||
"confirmed_modes": {}
|
||||
},
|
||||
"-1": {
|
||||
"dxcc": "-1",
|
||||
"cc": "-",
|
||||
|
|
|
@ -22,6 +22,15 @@
|
|||
<script src="./lib/protos.js" type="text/javascript"></script>
|
||||
<script src="./lib/third-party.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster/prepareRosterSettings.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster/processRosterFiltering.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster/processRosterHunting.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster/renderCompactRoster.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster/renderNormalRoster.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster/renderRoster.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster/rosterColumns.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster/rosterColumnFunctions.js" type="text/javascript"></script>
|
||||
<script src="./lib/roster/sendAlerts.js" type="text/javascript"></script>
|
||||
<script src="./lib/screens.js"></script>
|
||||
</head>
|
||||
<body onload="init()" class="roster" oncontextmenu="return handleContextMenu(event);">
|
||||
|
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
|
@ -1,4 +1,4 @@
|
|||
// GridTracker Copyright © 2021 GridTracker.org
|
||||
// GridTracker Copyright © 2022 GridTracker.org
|
||||
// All rights reserved.
|
||||
// See LICENSE for more information.
|
||||
|
||||
|
@ -86,36 +86,6 @@ function onAdiLoadComplete(adiBuffer, saveAdifFile, adifFileName, newFile)
|
|||
{
|
||||
let finalMode = "";
|
||||
|
||||
let appLoTW_RXQSO = findAdiField(
|
||||
activeAdifArray[x],
|
||||
"APP_LoTW_RXQSO"
|
||||
);
|
||||
|
||||
if (appLoTW_RXQSO != "")
|
||||
{
|
||||
let dRXQSO = Date.parse(appLoTW_RXQSO);
|
||||
let dLastLOTW_QSO = Date.parse(g_adifLogSettings.lastFetch.lotw_qso);
|
||||
if ((isNaN(dRXQSO) == false) && (isNaN(dLastLOTW_QSO) == false) && (dRXQSO > dLastLOTW_QSO))
|
||||
{
|
||||
g_adifLogSettings.lastFetch.lotw_qso = appLoTW_RXQSO;
|
||||
}
|
||||
}
|
||||
|
||||
let appLoTW_RXQSL = findAdiField(
|
||||
activeAdifArray[x],
|
||||
"APP_LoTW_RXQSL"
|
||||
);
|
||||
|
||||
if (appLoTW_RXQSL != "")
|
||||
{
|
||||
let dRXQSL = Date.parse(appLoTW_RXQSL);
|
||||
let dLastLOTW_QSL = Date.parse(g_adifLogSettings.lastFetch.lotw_qsl);
|
||||
if ((isNaN(dRXQSL) == false) && (isNaN(dLastLOTW_QSL) == false) && (dRXQSL > dLastLOTW_QSL))
|
||||
{
|
||||
g_adifLogSettings.lastFetch.lotw_qsl = appLoTW_RXQSL;
|
||||
}
|
||||
}
|
||||
|
||||
if (activeAdifArray[x].length > 3)
|
||||
{
|
||||
if (activeAdifLogMode)
|
||||
|
@ -1668,7 +1638,7 @@ function sendTcpMessage(msg, length, port, address)
|
|||
client.setTimeout(30000);
|
||||
client.connect(port, address, function ()
|
||||
{
|
||||
client.write(msg);
|
||||
client.write(Buffer.from(msg, "utf-8"));
|
||||
});
|
||||
|
||||
client.on("close", function () {});
|
||||
|
@ -1677,7 +1647,7 @@ function sendTcpMessage(msg, length, port, address)
|
|||
function valueToAdiField(field, value)
|
||||
{
|
||||
var adi = "<" + field + ":";
|
||||
adi += String(value).length + ">";
|
||||
adi += Buffer.byteLength(String(value)) + ">";
|
||||
adi += String(value) + " ";
|
||||
return adi;
|
||||
}
|
||||
|
@ -1957,7 +1927,7 @@ function finishSendingReport(record, localMode)
|
|||
|
||||
for (let key in record)
|
||||
{
|
||||
report += "<" + key + ":" + record[key].length + ">" + record[key] + " ";
|
||||
report += "<" + key + ":" + Buffer.byteLength(record[key]) + ">" + record[key] + " ";
|
||||
}
|
||||
report += "<EOR>";
|
||||
|
||||
|
@ -2139,7 +2109,7 @@ function finishSendingReport(record, localMode)
|
|||
for (var key in record)
|
||||
{
|
||||
report +=
|
||||
"<" + key + ":" + record[key].length + ">" + record[key] + " ";
|
||||
"<" + key + ":" + Buffer.byteLength(record[key]) + ">" + record[key] + " ";
|
||||
}
|
||||
report += "<EOR>";
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// GridTracker Copyright © 2021 GridTracker.org
|
||||
// GridTracker Copyright © 2022 GridTracker.org
|
||||
// All rights reserved.
|
||||
// See LICENSE for more information.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// GridTracker Copyright © 2021 GridTracker.org
|
||||
// GridTracker Copyright © 2022 GridTracker.org
|
||||
// All rights reserved.
|
||||
// See LICENSE for more information.
|
||||
|
||||
|
@ -279,7 +279,7 @@ function oqrsDownload(fromSettings)
|
|||
{
|
||||
oqrsUpdatedTd.innerHTML = "<b><i>Downloading...</i></b>";
|
||||
getBuffer(
|
||||
"http://app.gridtracker.org/callsigns/clublog.json",
|
||||
"https://storage.googleapis.com/gt_app/callsigns/clublog.json",
|
||||
processoqrsCallsigns,
|
||||
null,
|
||||
"http",
|
||||
|
@ -539,7 +539,7 @@ function ulsDownload()
|
|||
ulsUpdatedTd.innerHTML = "<b><i>Downloading...</i></b>";
|
||||
ulsCountTd.innerHTML = 0;
|
||||
getChunkedBuffer(
|
||||
"http://app.gridtracker.org/callsigns/callsigns.txt",
|
||||
"https://storage.googleapis.com/gt_app/callsigns/callsigns.txt",
|
||||
processulsCallsigns,
|
||||
null,
|
||||
"http",
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
// FIXME ****************************************************************************** //
|
||||
// The datepicker's "Time" section doesn't work. This really needs to be fixed before
|
||||
// the next big RTTY Roundup or Field Day where there may be a lot of hams that want
|
||||
// to use this feature to only reference their log starting when the contest starts.
|
||||
// Which isn't always 00:00 UTC.
|
||||
// ************************************************************************************ //
|
||||
var picker = {
|
||||
attach: function (opt)
|
||||
{
|
||||
|
|
|
@ -1,265 +1,266 @@
|
|||
var validSettings = [
|
||||
"HRDLogbookLogSettings",
|
||||
"N1MMSettings",
|
||||
"acLogSettings",
|
||||
"adifLogSettings",
|
||||
"alertSettings",
|
||||
"appSettings",
|
||||
"audioSettings",
|
||||
"awardTracker",
|
||||
"bandActivity",
|
||||
"blockedCQ",
|
||||
"blockedCalls",
|
||||
"blockedDxcc",
|
||||
"callsignLookups",
|
||||
"classicAlerts",
|
||||
"classicAlertsVersion",
|
||||
"currentVersion",
|
||||
"dxkLogSettings",
|
||||
"log4OMSettings",
|
||||
"mapMemory",
|
||||
"mapSettings",
|
||||
"msgSettings",
|
||||
"receptionSettings",
|
||||
"rosterSettings",
|
||||
"savedAlerts",
|
||||
"speechSettings",
|
||||
"startupLogs",
|
||||
"trustedQslSettings",
|
||||
"screenSettings",
|
||||
"legendColors"
|
||||
];
|
||||
|
||||
var def_appSettings = {
|
||||
alertMute: 0,
|
||||
rosterAlwaysOnTop: false,
|
||||
centerGridsquare: "",
|
||||
chatUUID: "",
|
||||
crScript: 0,
|
||||
distanceUnit: "MI",
|
||||
earthImgSrc: 0,
|
||||
gridViewMode: 3,
|
||||
gridsquareDecayTime: 300,
|
||||
gtAgree: "",
|
||||
gtBandFilter: "",
|
||||
gtFlagImgSrc: 0,
|
||||
gtModeFilter: "",
|
||||
gtPropFilter: "mixed",
|
||||
gtMsgEnable: true,
|
||||
gtShareEnable: true,
|
||||
heatEnabled: 0,
|
||||
loadAdifAtStartup: false,
|
||||
lookupLoginCq: "",
|
||||
lookupLoginQrz: "",
|
||||
lookupLoginQth: "",
|
||||
lookupOnTx: false,
|
||||
lookupCloseLog: false,
|
||||
lookupMerge: true,
|
||||
lookupMissingGrid: false,
|
||||
lookupPasswordCq: "",
|
||||
lookupPasswordQrz: "",
|
||||
lookupPasswordQth: "",
|
||||
lookupService: "CALLOOK",
|
||||
lookupCallookPreferred: false,
|
||||
moonPath: 0,
|
||||
moonTrack: 0,
|
||||
mouseTrack: 0,
|
||||
multicast: false,
|
||||
myBand: "OOB",
|
||||
myDEGrid: "",
|
||||
myDEcall: "NOCALL",
|
||||
myMode: "",
|
||||
myRawCall: "NOCALL",
|
||||
myRawFreq: "",
|
||||
myRawGrid: "",
|
||||
pathWidthWeight: 1.0,
|
||||
pushPinMode: false,
|
||||
qrzPathWidthWeight: 1.2,
|
||||
sixWideMode: 0,
|
||||
savedAppData: null,
|
||||
soundCard: "default",
|
||||
spotsEnabled: 0,
|
||||
stopAskingVersion: false,
|
||||
useLocalTime: 0,
|
||||
wsjtForwardUdpEnable: false,
|
||||
wsjtForwardUdpIp: "127.0.0.1",
|
||||
wsjtForwardUdpPort: 2238,
|
||||
wsjtIP: "",
|
||||
wsjtUdpPort: 0,
|
||||
workingCallsignEnable: false,
|
||||
workingCallsigns: {},
|
||||
workingDateEnable: false,
|
||||
workingDate: 0,
|
||||
gtSpotEnable: true
|
||||
};
|
||||
|
||||
var def_mapSettings = {
|
||||
animate: true,
|
||||
animateSpeed: 4,
|
||||
CQhilite: true,
|
||||
fitQRZ: false,
|
||||
focusRig: true,
|
||||
gridAlpha: 136,
|
||||
haltAllOnTx: true,
|
||||
legend: true,
|
||||
longitude: 0.0,
|
||||
latitude: 0.0,
|
||||
loudness: 1,
|
||||
mapIndex: 19,
|
||||
mergeOverlay: false,
|
||||
mouseOver: true,
|
||||
nightLoudness: 0.8,
|
||||
nightMapEnable: false,
|
||||
nightMapIndex: 20,
|
||||
nightPathColor: 361,
|
||||
nightQrzPathColor: 1,
|
||||
offlineMode: false,
|
||||
pathColor: 0,
|
||||
qrzDxccFallback: false,
|
||||
qrzPathColor: 1,
|
||||
rosterTime: 120,
|
||||
shadow: 0.1,
|
||||
splitQSL: true,
|
||||
strikes: false,
|
||||
strikesAlert: 2,
|
||||
strikesGlobal: false,
|
||||
strikesNotify: false,
|
||||
trafficDecode: true,
|
||||
usNexrad: false,
|
||||
zoom: 4,
|
||||
mapTrans: 0.5
|
||||
};
|
||||
|
||||
var def_adifLogSettings = {
|
||||
menu: {
|
||||
buttonAdifCheckBox: false,
|
||||
buttonClubCheckBox: false,
|
||||
buttonLOTWCheckBox: false,
|
||||
buttonQRZCheckBox: false,
|
||||
buttonPsk24CheckBox: true
|
||||
},
|
||||
startup: {
|
||||
loadAdifCheckBox: false,
|
||||
loadPsk24CheckBox: false,
|
||||
loadQRZCheckBox: false,
|
||||
loadLOTWCheckBox: false,
|
||||
loadClubCheckBox: false,
|
||||
loadGTCheckBox: true
|
||||
},
|
||||
qsolog: {
|
||||
logQRZqsoCheckBox: false,
|
||||
logGTqsoCheckBox: true,
|
||||
logLOTWqsoCheckBox: false,
|
||||
logHRDLOGqsoCheckBox: false,
|
||||
logClubqsoCheckBox: false,
|
||||
logCloudlogQSOCheckBox: false,
|
||||
logeQSLQSOCheckBox: false
|
||||
},
|
||||
nickname: {
|
||||
nicknameeQSLCheckBox: false
|
||||
},
|
||||
text: {
|
||||
lotwLogin: "",
|
||||
clubCall: "",
|
||||
clubEmail: "",
|
||||
clubPassword: "",
|
||||
lotwPassword: "",
|
||||
lotwTrusted: "",
|
||||
lotwStation: "",
|
||||
qrzApiKey: "",
|
||||
HRDLOGCallsign: "",
|
||||
HRDLOGUploadCode: "",
|
||||
CloudlogURL: "http://127.0.0.1/index.php/api/qso",
|
||||
CloudlogAPI: "",
|
||||
eQSLUser: "",
|
||||
eQSLPassword: "",
|
||||
eQSLNickname: ""
|
||||
},
|
||||
downloads: {},
|
||||
lastFetch: {
|
||||
lotw_qso: "1970-01-01",
|
||||
lotw_qsl: "1970-01-01"
|
||||
}
|
||||
};
|
||||
|
||||
var def_msgSettings = {
|
||||
msgAlertSelect: 1,
|
||||
msgAlertWord: "New chat message",
|
||||
msgAlertMedia: "none",
|
||||
msgFrequencySelect: 0,
|
||||
msgActionSelect: 1,
|
||||
msgAwaySelect: 0,
|
||||
msgAwayText: "I am away from the shack at the moment"
|
||||
};
|
||||
|
||||
var def_receptionSettings = {
|
||||
lastSequenceNumber: "0", // Treat as a string, it's friggin big
|
||||
lastDownloadTimeSec: 0,
|
||||
viewHistoryTimeSec: 900,
|
||||
viewPaths: false,
|
||||
pathColor: -1,
|
||||
pathNightColor: 361,
|
||||
spotWidth: 0.8,
|
||||
mergeSpots: true
|
||||
};
|
||||
|
||||
var def_N1MMSettings = {
|
||||
enable: false,
|
||||
port: 2333,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_log4OMSettings = {
|
||||
enable: false,
|
||||
port: 2236,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_dxkLogSettings = {
|
||||
enable: false,
|
||||
port: 52000,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_HRDLogbookLogSettings = {
|
||||
enable: false,
|
||||
port: 7826,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_acLogSettings = {
|
||||
enable: false,
|
||||
port: 1100,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_trustedQslSettings = {
|
||||
stationFile: "",
|
||||
stationFileValid: false,
|
||||
binaryFile: "",
|
||||
binaryFileValid: false
|
||||
};
|
||||
var def_callsignLookups = {
|
||||
lotwUseEnable: true,
|
||||
lotwWeeklyEnable: true,
|
||||
lotwLastUpdate: 0,
|
||||
eqslUseEnable: true,
|
||||
eqslWeeklyEnable: true,
|
||||
eqslLastUpdate: 0,
|
||||
ulsUseEnable: true,
|
||||
ulsWeeklyEnable: true,
|
||||
ulsLastUpdate: 0,
|
||||
oqrsUseEnable: false,
|
||||
oqrsWeeklyEnable: false,
|
||||
oqrsLastUpdate: 0
|
||||
};
|
||||
|
||||
var def_bandActivity = {
|
||||
lastUpdate: {},
|
||||
lines: {}
|
||||
};
|
||||
|
||||
var def_legendColors = {
|
||||
QSO: "#EEEE00",
|
||||
QSL: "#EE0000",
|
||||
QSX: "#1111EE",
|
||||
CQ: "#00FF00",
|
||||
CQDX: "#00FFFF",
|
||||
QRZ: "#FFFF00",
|
||||
QTH: "#FFA600"
|
||||
};
|
||||
var validSettings = [
|
||||
"HRDLogbookLogSettings",
|
||||
"N1MMSettings",
|
||||
"acLogSettings",
|
||||
"adifLogSettings",
|
||||
"alertSettings",
|
||||
"appSettings",
|
||||
"audioSettings",
|
||||
"awardTracker",
|
||||
"bandActivity",
|
||||
"blockedCQ",
|
||||
"blockedCalls",
|
||||
"blockedDxcc",
|
||||
"callsignLookups",
|
||||
"classicAlerts",
|
||||
"classicAlertsVersion",
|
||||
"currentVersion",
|
||||
"dxkLogSettings",
|
||||
"log4OMSettings",
|
||||
"mapMemory",
|
||||
"mapSettings",
|
||||
"msgSettings",
|
||||
"receptionSettings",
|
||||
"rosterSettings",
|
||||
"savedAlerts",
|
||||
"speechSettings",
|
||||
"startupLogs",
|
||||
"trustedQslSettings",
|
||||
"screenSettings",
|
||||
"legendColors"
|
||||
];
|
||||
|
||||
var def_appSettings = {
|
||||
alertMute: 0,
|
||||
rosterAlwaysOnTop: false,
|
||||
centerGridsquare: "",
|
||||
chatUUID: "",
|
||||
crScript: 0,
|
||||
distanceUnit: "MI",
|
||||
earthImgSrc: 0,
|
||||
gridViewMode: 3,
|
||||
gridsquareDecayTime: 300,
|
||||
gtAgree: "",
|
||||
gtBandFilter: "",
|
||||
gtFlagImgSrc: 0,
|
||||
gtModeFilter: "",
|
||||
gtPropFilter: "mixed",
|
||||
gtMsgEnable: true,
|
||||
gtShareEnable: true,
|
||||
heatEnabled: 0,
|
||||
loadAdifAtStartup: false,
|
||||
lookupLoginCq: "",
|
||||
lookupLoginQrz: "",
|
||||
lookupLoginQth: "",
|
||||
lookupOnTx: false,
|
||||
lookupCloseLog: false,
|
||||
lookupMerge: true,
|
||||
lookupMissingGrid: false,
|
||||
lookupPasswordCq: "",
|
||||
lookupPasswordQrz: "",
|
||||
lookupPasswordQth: "",
|
||||
lookupService: "CALLOOK",
|
||||
lookupCallookPreferred: false,
|
||||
clearRosterOnBandChange: false,
|
||||
moonPath: 0,
|
||||
moonTrack: 0,
|
||||
mouseTrack: 0,
|
||||
multicast: false,
|
||||
myBand: "OOB",
|
||||
myDEGrid: "",
|
||||
myDEcall: "NOCALL",
|
||||
myMode: "",
|
||||
myRawCall: "NOCALL",
|
||||
myRawFreq: "",
|
||||
myRawGrid: "",
|
||||
pathWidthWeight: 1.0,
|
||||
pushPinMode: false,
|
||||
qrzPathWidthWeight: 1.2,
|
||||
sixWideMode: 0,
|
||||
savedAppData: null,
|
||||
soundCard: "default",
|
||||
spotsEnabled: 0,
|
||||
stopAskingVersion: false,
|
||||
useLocalTime: 0,
|
||||
wsjtForwardUdpEnable: false,
|
||||
wsjtForwardUdpIp: "127.0.0.1",
|
||||
wsjtForwardUdpPort: 2238,
|
||||
wsjtIP: "",
|
||||
wsjtUdpPort: 0,
|
||||
workingCallsignEnable: false,
|
||||
workingCallsigns: {},
|
||||
workingDateEnable: false,
|
||||
workingDate: 0,
|
||||
gtSpotEnable: true
|
||||
};
|
||||
|
||||
var def_mapSettings = {
|
||||
animate: true,
|
||||
animateSpeed: 4,
|
||||
CQhilite: true,
|
||||
fitQRZ: false,
|
||||
focusRig: true,
|
||||
gridAlpha: 136,
|
||||
haltAllOnTx: true,
|
||||
legend: true,
|
||||
longitude: 0.0,
|
||||
latitude: 0.0,
|
||||
loudness: 1,
|
||||
mapIndex: 19,
|
||||
mergeOverlay: false,
|
||||
mouseOver: true,
|
||||
nightLoudness: 0.8,
|
||||
nightMapEnable: false,
|
||||
nightMapIndex: 20,
|
||||
nightPathColor: 361,
|
||||
nightQrzPathColor: 1,
|
||||
offlineMode: false,
|
||||
pathColor: 0,
|
||||
qrzDxccFallback: false,
|
||||
qrzPathColor: 1,
|
||||
rosterTime: 120,
|
||||
shadow: 0.1,
|
||||
splitQSL: true,
|
||||
strikes: false,
|
||||
strikesAlert: 2,
|
||||
strikesGlobal: false,
|
||||
strikesNotify: false,
|
||||
trafficDecode: true,
|
||||
usNexrad: false,
|
||||
zoom: 4,
|
||||
mapTrans: 0.5
|
||||
};
|
||||
|
||||
var def_adifLogSettings = {
|
||||
menu: {
|
||||
buttonAdifCheckBox: false,
|
||||
buttonClubCheckBox: false,
|
||||
buttonLOTWCheckBox: false,
|
||||
buttonQRZCheckBox: false,
|
||||
buttonPsk24CheckBox: true
|
||||
},
|
||||
startup: {
|
||||
loadAdifCheckBox: false,
|
||||
loadPsk24CheckBox: false,
|
||||
loadQRZCheckBox: false,
|
||||
loadLOTWCheckBox: false,
|
||||
loadClubCheckBox: false,
|
||||
loadGTCheckBox: true
|
||||
},
|
||||
qsolog: {
|
||||
logQRZqsoCheckBox: false,
|
||||
logGTqsoCheckBox: true,
|
||||
logLOTWqsoCheckBox: false,
|
||||
logHRDLOGqsoCheckBox: false,
|
||||
logClubqsoCheckBox: false,
|
||||
logCloudlogQSOCheckBox: false,
|
||||
logeQSLQSOCheckBox: false
|
||||
},
|
||||
nickname: {
|
||||
nicknameeQSLCheckBox: false
|
||||
},
|
||||
text: {
|
||||
lotwLogin: "",
|
||||
clubCall: "",
|
||||
clubEmail: "",
|
||||
clubPassword: "",
|
||||
lotwPassword: "",
|
||||
lotwTrusted: "",
|
||||
lotwStation: "",
|
||||
qrzApiKey: "",
|
||||
HRDLOGCallsign: "",
|
||||
HRDLOGUploadCode: "",
|
||||
CloudlogURL: "http://127.0.0.1/index.php/api/qso",
|
||||
CloudlogAPI: "",
|
||||
eQSLUser: "",
|
||||
eQSLPassword: "",
|
||||
eQSLNickname: ""
|
||||
},
|
||||
downloads: {},
|
||||
lastFetch: {
|
||||
lotw_qso: "1970-01-01",
|
||||
lotw_qsl: "1970-01-01"
|
||||
}
|
||||
};
|
||||
|
||||
var def_msgSettings = {
|
||||
msgAlertSelect: 1,
|
||||
msgAlertWord: "New chat message",
|
||||
msgAlertMedia: "none",
|
||||
msgFrequencySelect: 0,
|
||||
msgActionSelect: 1,
|
||||
msgAwaySelect: 0,
|
||||
msgAwayText: "I am away from the shack at the moment"
|
||||
};
|
||||
|
||||
var def_receptionSettings = {
|
||||
lastSequenceNumber: "0", // Treat as a string, it's friggin big
|
||||
lastDownloadTimeSec: 0,
|
||||
viewHistoryTimeSec: 900,
|
||||
viewPaths: false,
|
||||
pathColor: -1,
|
||||
pathNightColor: 361,
|
||||
spotWidth: 0.8,
|
||||
mergeSpots: true
|
||||
};
|
||||
|
||||
var def_N1MMSettings = {
|
||||
enable: false,
|
||||
port: 2333,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_log4OMSettings = {
|
||||
enable: false,
|
||||
port: 2236,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_dxkLogSettings = {
|
||||
enable: false,
|
||||
port: 52000,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_HRDLogbookLogSettings = {
|
||||
enable: false,
|
||||
port: 7826,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_acLogSettings = {
|
||||
enable: false,
|
||||
port: 1100,
|
||||
ip: "127.0.0.1"
|
||||
};
|
||||
var def_trustedQslSettings = {
|
||||
stationFile: "",
|
||||
stationFileValid: false,
|
||||
binaryFile: "",
|
||||
binaryFileValid: false
|
||||
};
|
||||
var def_callsignLookups = {
|
||||
lotwUseEnable: true,
|
||||
lotwWeeklyEnable: true,
|
||||
lotwLastUpdate: 0,
|
||||
eqslUseEnable: true,
|
||||
eqslWeeklyEnable: true,
|
||||
eqslLastUpdate: 0,
|
||||
ulsUseEnable: true,
|
||||
ulsWeeklyEnable: true,
|
||||
ulsLastUpdate: 0,
|
||||
oqrsUseEnable: false,
|
||||
oqrsWeeklyEnable: false,
|
||||
oqrsLastUpdate: 0
|
||||
};
|
||||
|
||||
var def_bandActivity = {
|
||||
lastUpdate: {},
|
||||
lines: {}
|
||||
};
|
||||
|
||||
var def_legendColors = {
|
||||
QSO: "#EEEE00",
|
||||
QSL: "#EE0000",
|
||||
QSX: "#1111EE",
|
||||
CQ: "#00FF00",
|
||||
CQDX: "#00FFFF",
|
||||
QRZ: "#FFFF00",
|
||||
QTH: "#FFA600"
|
||||
};
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// GridTracker Copyright © 2021 GridTracker.org
|
||||
// GridTracker Copyright © 2022 GridTracker.org
|
||||
// All rights reserved.
|
||||
// See LICENSE for more information.
|
||||
const pjson = require("./package.json");
|
||||
var gtVersion = parseInt(pjson.version.replace(/\./g, ""));
|
||||
var gtVersionStr = pjson.version
|
||||
var gtVersion = parseInt(gtVersionStr.replace(/\./g, ""));
|
||||
var gtBeta = pjson.betaVersion;
|
||||
|
||||
var g_startVersion = 0;
|
||||
|
@ -116,14 +117,7 @@ function loadAllSettings()
|
|||
def_adifLogSettings
|
||||
);
|
||||
g_msgSettings = loadDefaultsAndMerge("msgSettings", def_msgSettings);
|
||||
// one-time override of oams pop-up messages: if pop-ups disabled
|
||||
// and new version, reset msgActionSelect to 1 (pop up)
|
||||
if (g_msgSettings.msgActionSelect == 0 &&
|
||||
String(gtVersion) != String(g_startVersion))
|
||||
{
|
||||
g_msgSettings.msgActionSelect = 1;
|
||||
localStorage.msgSettings = JSON.stringify(g_msgSettings);
|
||||
}
|
||||
|
||||
g_receptionSettings = loadDefaultsAndMerge(
|
||||
"receptionSettings",
|
||||
def_receptionSettings
|
||||
|
@ -1098,7 +1092,11 @@ function addDeDx(
|
|||
details.grid.length < 6 &&
|
||||
(details.grid.substr(0, 4) == finalGrid.substr(0, 4) ||
|
||||
details.grid.length == 0)
|
||||
) { details.grid = finalGrid; }
|
||||
)
|
||||
{
|
||||
details.grid = finalGrid;
|
||||
details.grid4 = finalGrid.substr(0, 4);
|
||||
}
|
||||
}
|
||||
if (finalRSTsent.length > 0) details.RSTsent = finalRSTsent;
|
||||
if (finalRSTrecv.length > 0) details.RSTrecv = finalRSTrecv;
|
||||
|
@ -1118,6 +1116,7 @@ function addDeDx(
|
|||
{
|
||||
details = {};
|
||||
details.grid = finalGrid;
|
||||
details.grid4 = finalGrid.length > 0 ? finalGrid.substr(0, 4) : "-";
|
||||
details.RSTsent = finalRSTsent;
|
||||
details.RSTrecv = finalRSTrecv;
|
||||
details.msg = "-";
|
||||
|
@ -1159,10 +1158,9 @@ function addDeDx(
|
|||
finalGrid.length > 0
|
||||
)
|
||||
{
|
||||
var fourGrid = finalGrid.substr(0, 4);
|
||||
if (fourGrid in g_gridToState && g_gridToState[fourGrid].length == 1)
|
||||
if (details.grid4 in g_gridToState && g_gridToState[details.grid4].length == 1)
|
||||
{
|
||||
details.state = g_gridToState[fourGrid][0];
|
||||
details.state = g_gridToState[details.grid4][0];
|
||||
}
|
||||
lookupCall = true;
|
||||
}
|
||||
|
@ -3108,30 +3106,23 @@ function makeTitleInfo(mapWindow)
|
|||
? myMode
|
||||
: g_appSettings.gtModeFilter;
|
||||
var space = " ";
|
||||
var news = "GridTracker [Band: " + band + " Mode: " + mode;
|
||||
var news = `GridTracker ${gtVersionStr} [Band: ${band} Mode: ${mode}`;
|
||||
var end = "]";
|
||||
|
||||
if (mapWindow)
|
||||
{
|
||||
news += " Layer: " + g_viewInfo[g_currentOverlay][1];
|
||||
news += ` Layer: ${g_viewInfo[g_currentOverlay][1]}`;
|
||||
}
|
||||
|
||||
if (g_currentOverlay == 0 && g_appSettings.gridViewMode == 1) { return news + end; }
|
||||
|
||||
var workline =
|
||||
" - Worked " +
|
||||
g_viewInfo[g_currentOverlay][2] +
|
||||
" Confirmed " +
|
||||
g_viewInfo[g_currentOverlay][3];
|
||||
var workline = ` - Worked ${g_viewInfo[g_currentOverlay][2]} Confirmed ${g_viewInfo[g_currentOverlay][3]}`
|
||||
if (
|
||||
g_viewInfo[g_currentOverlay][2] <= g_viewInfo[g_currentOverlay][4] &&
|
||||
g_viewInfo[g_currentOverlay][4] > 0
|
||||
)
|
||||
{
|
||||
end =
|
||||
" Needed " +
|
||||
(g_viewInfo[g_currentOverlay][4] - g_viewInfo[g_currentOverlay][2]) +
|
||||
"]";
|
||||
end = ` Needed ${(g_viewInfo[g_currentOverlay][4] - g_viewInfo[g_currentOverlay][2])}]`;
|
||||
}
|
||||
return news + workline + end;
|
||||
}
|
||||
|
@ -10112,7 +10103,7 @@ function renderStatsBox()
|
|||
worker +=
|
||||
"<br/> In Section: " +
|
||||
scoreSection +
|
||||
"<br/>Error Generating Stats<br/>Please take a screenshot and send to gridtracker@gmail.com";
|
||||
"<br/>Error Generating Stats<br/>Please take a screenshot and send to team@gridtracker.org";
|
||||
}
|
||||
|
||||
setStatsDiv("statViewDiv", worker);
|
||||
|
@ -11183,7 +11174,7 @@ function checkForNewVersion(showUptoDate)
|
|||
if (typeof nw != "undefined")
|
||||
{
|
||||
getBuffer(
|
||||
"http://app.gridtracker.org/version.txt?lang=",
|
||||
"https://storage.googleapis.com/gt_app/version.txt",
|
||||
versionCheck,
|
||||
showUptoDate,
|
||||
"http",
|
||||
|
@ -11197,20 +11188,15 @@ function downloadAcknowledgements()
|
|||
if (g_mapSettings.offlineMode == false)
|
||||
{
|
||||
getBuffer(
|
||||
"http://app.gridtracker.org/acknowledgements.json",
|
||||
"https://storage.googleapis.com/gt_app/acknowledgements.json",
|
||||
updateAcks,
|
||||
null,
|
||||
"http",
|
||||
80
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function checkForNewAcknowledgements()
|
||||
{
|
||||
downloadAcknowledgements();
|
||||
setTimeout(checkForNewAcknowledgements, 8640000);
|
||||
readAcksFromDisk();
|
||||
setTimeout(downloadAcknowledgements, 8640000);
|
||||
}
|
||||
}
|
||||
|
||||
function renderBandActivity()
|
||||
|
@ -11352,7 +11338,13 @@ function pskBandActivityCallback(buffer, flag)
|
|||
|
||||
renderBandActivity();
|
||||
}
|
||||
|
||||
/* FIXME ******************************************************************************
|
||||
Should we somewhere in settings, have a checkbox to enable / disable PSK spots
|
||||
specifically? We can disable the overall spots, both PSK and OAMS, and OAMS has a
|
||||
checkbox in the OAMS tab. I'm thinking for the situation where I only want to
|
||||
pull in OAMS spots and not PSK reporter's spots.
|
||||
************************************************************************************
|
||||
*/
|
||||
function pskGetBandActivity()
|
||||
{
|
||||
if (g_mapSettings.offlineMode == true) return;
|
||||
|
@ -11616,14 +11608,7 @@ function updateBasedOnIni()
|
|||
{
|
||||
if (typeof nw != "undefined")
|
||||
{
|
||||
// lets see if we can find our location the hard way
|
||||
getBuffer(
|
||||
"https://api.ipstack.com/check?access_key=8c9233ec1c09861a707951ab3718a7f6&format=1",
|
||||
ipLocation,
|
||||
null,
|
||||
"https",
|
||||
443
|
||||
);
|
||||
alert("Location not available!\nEither start WSJT-X/JTDX or enter your grid square in the settings ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12101,27 +12086,6 @@ function selectElementContents(el)
|
|||
}
|
||||
}
|
||||
|
||||
function ipLocation(buffer, flag)
|
||||
{
|
||||
var obj = JSON.parse(buffer);
|
||||
if (
|
||||
typeof obj != "undefined" &&
|
||||
obj != null &&
|
||||
typeof obj.latitude != "undefined"
|
||||
)
|
||||
{
|
||||
g_appSettings.centerGridsquare = latLonToGridSquare(
|
||||
obj.latitude,
|
||||
obj.longitude
|
||||
).substr(0, 6);
|
||||
if (g_appSettings.centerGridsquare.length > 0)
|
||||
{
|
||||
homeQTHInput.value = g_appSettings.centerGridsquare;
|
||||
if (ValidateGridsquare(homeQTHInput, null)) setCenterGridsquare();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function popupNewWindows()
|
||||
{
|
||||
if (typeof nw != "undefined")
|
||||
|
@ -12179,7 +12143,7 @@ function callsignToDxcc(insign)
|
|||
{
|
||||
if (parts[end].toUpperCase() == "MM")
|
||||
{
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
parts.pop();
|
||||
end = parts.length - 1;
|
||||
|
@ -12766,8 +12730,7 @@ function updateAcks(buffer)
|
|||
{
|
||||
try
|
||||
{
|
||||
g_acks = JSON.parse(buffer);
|
||||
fs.writeFileSync(g_NWappData + "acknowledgements.json", JSON.stringify(g_acks));
|
||||
g_acknowledgedCalls = JSON.parse(buffer);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
|
@ -13004,6 +12967,7 @@ function loadMapSettings()
|
|||
focusRigValue.checked = g_mapSettings.focusRig;
|
||||
haltAllOnTxValue.checked = g_mapSettings.haltAllOnTx;
|
||||
strikesAlert.value = g_mapSettings.strikesAlert;
|
||||
clearRosterOnBandChange.checked = g_appSettings.clearRosterOnBandChange;
|
||||
|
||||
setStrikesButton();
|
||||
|
||||
|
@ -14435,6 +14399,11 @@ function loadLookupDetails()
|
|||
else lookupCredentials.style.display = "block";
|
||||
}
|
||||
|
||||
function clearRosterOnBandChangeValueChanged(what)
|
||||
{
|
||||
g_appSettings.clearRosterOnBandChange = clearRosterOnBandChange.checked;
|
||||
}
|
||||
|
||||
function lookupValueChanged(what)
|
||||
{
|
||||
if (g_appSettings.lookupService != lookupService.value)
|
||||
|
@ -14630,6 +14599,7 @@ function callookResults(buffer, gridPass)
|
|||
callObject.lat = results.location.latitude;
|
||||
callObject.lon = results.location.longitude;
|
||||
callObject.grid = results.location.gridsquare;
|
||||
callObject.grid4 = callObject.grid.length > 1 ? callObject.grid.substr(0, 4) : "-";
|
||||
callObject.efdate = results.otherInfo.grantDate;
|
||||
callObject.expdate = results.otherInfo.expiryDate;
|
||||
callObject.frn = results.otherInfo.frn;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// GridTracker Copyright © 2021 GridTracker.org
|
||||
// GridTracker Copyright © 2022 GridTracker.org
|
||||
// All rights reserved.
|
||||
// See LICENSE for more information.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// GridTracker Copyright © 2021 GridTracker.org
|
||||
// GridTracker Copyright © 2022 GridTracker.org
|
||||
// All rights reserved.
|
||||
// See LICENSE for more information.
|
||||
|
||||
|
@ -129,6 +129,27 @@ Number.prototype.toDHMS = function ()
|
|||
return val;
|
||||
};
|
||||
|
||||
Number.prototype.toDHMS15 = function ()
|
||||
{
|
||||
// round to earliest 15 seconds
|
||||
|
||||
var seconds = Math.floor(this / 15) * 15;
|
||||
var days = Math.floor(seconds / (3600 * 24));
|
||||
seconds -= days * 3600 * 24;
|
||||
var hrs = Math.floor(seconds / 3600);
|
||||
seconds -= hrs * 3600;
|
||||
var mnts = Math.floor(seconds / 60);
|
||||
seconds -= mnts * 60;
|
||||
|
||||
days = days ? days + "d " : "";
|
||||
hrs = hrs ? hrs + "h " : "";
|
||||
mnts = mnts ? mnts + "m " : "";
|
||||
var first = days + hrs + mnts;
|
||||
if (first == "") val = seconds + "s";
|
||||
else val = first + (seconds > 0 ? seconds + "s" : "");
|
||||
return val;
|
||||
};
|
||||
|
||||
Number.prototype.toDHM = function ()
|
||||
{
|
||||
var seconds = this;
|
||||
|
@ -141,8 +162,10 @@ Number.prototype.toDHM = function ()
|
|||
|
||||
days = days ? days + "d " : "";
|
||||
hrs = hrs ? hrs + "h " : "";
|
||||
mnts = mnts ? mnts + "m " : "";
|
||||
mnts = mnts || seconds ? mnts + "m " : "";
|
||||
val = days + hrs + mnts;
|
||||
if (val == "") val = "0m";
|
||||
|
||||
return val;
|
||||
};
|
||||
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,83 @@
|
|||
function prepareRosterSettings()
|
||||
{
|
||||
let rosterSettings = {
|
||||
bands: {},
|
||||
modes: {},
|
||||
callMode: g_rosterSettings.callsign,
|
||||
onlyHits: false,
|
||||
isAwardTracker: false,
|
||||
now: timeNowSec()
|
||||
}
|
||||
|
||||
if (rosterSettings.callMode == "hits")
|
||||
{
|
||||
rosterSettings.callMode = "all"
|
||||
rosterSettings.onlyHits = true;
|
||||
}
|
||||
if (referenceNeed.value == LOGBOOK_AWARD_TRACKER)
|
||||
{
|
||||
rosterSettings.callMode = "all";
|
||||
rosterSettings.onlyHits = false;
|
||||
rosterSettings.isAwardTracker = true;
|
||||
g_rosterSettings.huntNeed = "confirmed";
|
||||
}
|
||||
// this appears to be determine if we should show the OAMS column
|
||||
// if the user is not in offline mode and has OAMS enabled, this could
|
||||
// be it's own function maybe?
|
||||
rosterSettings.canMsg =
|
||||
window.opener.g_mapSettings.offlineMode == false &&
|
||||
window.opener.g_appSettings.gtShareEnable == "true" &&
|
||||
window.opener.g_appSettings.gtMsgEnable == "true";
|
||||
|
||||
// The following 3 sections deal with QSLing, do we break them out
|
||||
// individually or lump them into a qslUser function that sets
|
||||
// all three at the same time?
|
||||
// this section is for LoTW users, can be a function
|
||||
if (window.opener.g_callsignLookups.lotwUseEnable == true)
|
||||
{
|
||||
usesLoTWDiv.style.display = "";
|
||||
if (g_rosterSettings.usesLoTW == true)
|
||||
{
|
||||
maxLoTW.style.display = "";
|
||||
maxLoTWView.style.display = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
maxLoTW.style.display = "none";
|
||||
maxLoTWView.style.display = "none";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
usesLoTWDiv.style.display = "none";
|
||||
maxLoTW.style.display = "none";
|
||||
maxLoTWView.style.display = "none";
|
||||
}
|
||||
|
||||
if (g_rosterSettings.huntNeed == "mixed")
|
||||
{
|
||||
rosterSettings.huntIndex = g_confirmed;
|
||||
rosterSettings.workedIndex = g_worked;
|
||||
rosterSettings.layeredMode = LAYERED_MODE_FOR[String(g_rosterSettings.reference)];
|
||||
}
|
||||
else if (g_rosterSettings.huntNeed == "worked")
|
||||
{
|
||||
rosterSettings.huntIndex = g_worked;
|
||||
rosterSettings.workedIndex = false;
|
||||
rosterSettings.layeredMode = false;
|
||||
}
|
||||
else if (g_rosterSettings.huntNeed == "confirmed")
|
||||
{
|
||||
rosterSettings.huntIndex = g_confirmed;
|
||||
rosterSettings.workedIndex = g_worked;
|
||||
rosterSettings.layeredMode = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
rosterSettings.huntIndex = false;
|
||||
rosterSettings.workedIndex = false;
|
||||
rosterSettings.layeredMode = false;
|
||||
}
|
||||
|
||||
return rosterSettings
|
||||
}
|
|
@ -0,0 +1,384 @@
|
|||
function processRosterFiltering(callRoster, rosterSettings)
|
||||
{
|
||||
// First loop, exclude calls, mostly based on "Exceptions" settings
|
||||
// this whole section is full of individual if's that could be broken out
|
||||
for (let callHash in callRoster)
|
||||
{
|
||||
let entry = callRoster[callHash];
|
||||
let callObj = entry.callObj;
|
||||
|
||||
let call = entry.DEcall;
|
||||
|
||||
entry.tx = true;
|
||||
callObj.shouldAlert = false;
|
||||
callObj.reason = Array();
|
||||
callObj.awardReason = "Callsign";
|
||||
|
||||
if (rosterSettings.now - callObj.age > window.opener.g_mapSettings.rosterTime)
|
||||
{
|
||||
entry.tx = false;
|
||||
entry.alerted = false;
|
||||
callObj.qrz = false;
|
||||
callObj.reset = true;
|
||||
continue;
|
||||
}
|
||||
if (!callObj.dxcc || callObj.dxcc == -1)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (window.opener.g_instances[callObj.instance].crEnable == false)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (call in g_blockedCalls)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
entry.DXcall + " from All" in g_blockedCQ ||
|
||||
entry.DXcall + " from " + window.opener.g_dxccToAltName[callObj.dxcc] in g_blockedCQ
|
||||
)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (callObj.ituza in g_blockedITUz)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (callObj.cqza in g_blockedCQz)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (callObj.dxcc in g_blockedDxcc)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (g_rosterSettings.cqOnly == true && callObj.CQ == false)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (g_rosterSettings.useRegex && g_rosterSettings.callsignRegex.length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!call.match(g_rosterSettings.callsignRegex))
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
if (g_rosterSettings.requireGrid == true && callObj.grid.length != 4)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (g_rosterSettings.wantMinDB == true && entry.message.SR < g_rosterSettings.minDb)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (g_rosterSettings.wantMaxDT == true && Math.abs(entry.message.DT) > g_rosterSettings.maxDT)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (g_rosterSettings.wantMinFreq == true && entry.message.DF < g_rosterSettings.minFreq)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (g_rosterSettings.wantMaxFreq == true && entry.message.DF > g_rosterSettings.maxFreq)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_rosterSettings.noMsg == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (callObj.msg.match(g_rosterSettings.noMsgValue))
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
if (g_rosterSettings.onlyMsg == true)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!callObj.msg.match(g_rosterSettings.onlyMsgValue))
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
|
||||
if (callObj.dxcc == window.opener.g_myDXCC)
|
||||
{
|
||||
if (g_rosterSettings.noMyDxcc == true)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (g_rosterSettings.onlyMyDxcc == true)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (window.opener.g_callsignLookups.lotwUseEnable == true && g_rosterSettings.usesLoTW == true)
|
||||
{
|
||||
if (!(call in window.opener.g_lotwCallsigns))
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (g_rosterSettings.maxLoTW < 27)
|
||||
{
|
||||
let months = (g_day - window.opener.g_lotwCallsigns[call]) / 30;
|
||||
if (months > g_rosterSettings.maxLoTW)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (window.opener.g_callsignLookups.eqslUseEnable == true && g_rosterSettings.useseQSL == true)
|
||||
{
|
||||
if (!(call in window.opener.g_eqslCallsigns))
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (window.opener.g_callsignLookups.oqrsUseEnable == true && g_rosterSettings.usesOQRS == true)
|
||||
{
|
||||
if (!(call in window.opener.g_oqrsCallsigns))
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (rosterSettings.callMode != "all")
|
||||
{
|
||||
if (entry.DXcall == "CQ DX" && callObj.dxcc == window.opener.g_myDXCC)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
let hash = hashMaker(call, callObj, g_rosterSettings.reference);
|
||||
if (rosterSettings.callMode == "worked" && hash in g_worked.call)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (rosterSettings.callMode == "confirmed" && hash in g_confirmed.call)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_rosterSettings.hunting == "grid")
|
||||
{
|
||||
let hash = hashMaker(callObj.grid.substr(0, 4),
|
||||
callObj, g_rosterSettings.reference);
|
||||
if (rosterSettings.huntIndex && hash in rosterSettings.huntIndex.grid)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
if (callObj.grid.length == 0)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (g_rosterSettings.hunting == "dxcc")
|
||||
{
|
||||
let hash = hashMaker(String(callObj.dxcc),
|
||||
callObj, g_rosterSettings.reference);
|
||||
|
||||
if (rosterSettings.huntIndex && (hash in rosterSettings.huntIndex.dxcc))
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (callObj.dxcc === -1)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_rosterSettings.hunting == "dxccs" && r_currentDXCCs != -1)
|
||||
{
|
||||
if (callObj.dxcc != r_currentDXCCs)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_rosterSettings.hunting == "wpx")
|
||||
{
|
||||
if (String(callObj.px) == null)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
let hash = hashMaker(String(callObj.px),
|
||||
callObj, g_rosterSettings.reference);
|
||||
|
||||
if (rosterSettings.huntIndex && (hash in rosterSettings.huntIndex.px))
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_rosterSettings.hunting == "cq")
|
||||
{
|
||||
let huntTotal = callObj.cqza.length;
|
||||
if (huntTotal == 0 || !rosterSettings.huntIndex)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
let huntFound = 0;
|
||||
for (index in callObj.cqza)
|
||||
{
|
||||
let hash = hashMaker(callObj.cqza[index], callObj, g_rosterSettings.reference);
|
||||
|
||||
if (hash in rosterSettings.huntIndex.cqz) huntFound++;
|
||||
}
|
||||
if (huntFound == huntTotal)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_rosterSettings.hunting == "itu")
|
||||
{
|
||||
let huntTotal = callObj.ituza.length;
|
||||
if (huntTotal == 0 || !rosterSettings.huntIndex)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
let huntFound = 0;
|
||||
for (index in callObj.ituza)
|
||||
{
|
||||
let hash = hashMaker(callObj.ituza[index], callObj, g_rosterSettings.reference);
|
||||
|
||||
if (hash in rosterSettings.huntIndex.ituz) huntFound++;
|
||||
}
|
||||
if (huntFound == huntTotal)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (callObj.grid.length == 0)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_rosterSettings.hunting == "usstates" && window.opener.g_callsignLookups.ulsUseEnable == true)
|
||||
{
|
||||
let state = callObj.state;
|
||||
let finalDxcc = callObj.dxcc;
|
||||
if (finalDxcc == 291 || finalDxcc == 110 || finalDxcc == 6)
|
||||
{
|
||||
if (state in window.opener.g_StateData)
|
||||
{
|
||||
let hash = hashMaker(state, callObj, g_rosterSettings.reference);
|
||||
|
||||
if (rosterSettings.huntIndex && hash in rosterSettings.huntIndex.state)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else entry.tx = false;
|
||||
}
|
||||
else entry.tx = false;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (g_rosterSettings.hunting == "usstate" && g_currentUSCallsigns)
|
||||
{
|
||||
if (call in g_currentUSCallsigns)
|
||||
{
|
||||
// Do Nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (rosterSettings.isAwardTracker)
|
||||
{
|
||||
let tx = false;
|
||||
let baseHash = hashMaker("", callObj, g_rosterSettings.reference);
|
||||
|
||||
for (let award in g_awardTracker)
|
||||
{
|
||||
if (g_awardTracker[award].enable)
|
||||
{
|
||||
tx = testAward(award, callObj, baseHash);
|
||||
if (tx)
|
||||
{
|
||||
let x = g_awardTracker[award];
|
||||
|
||||
// TODO: Move award reason out of exclusions code?
|
||||
callObj.awardReason =
|
||||
g_awards[x.sponsor].awards[x.name].tooltip +
|
||||
" (" +
|
||||
g_awards[x.sponsor].sponsor +
|
||||
")";
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
entry.tx = tx;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,700 @@
|
|||
function processRosterHunting(callRoster, rosterSettings)
|
||||
{
|
||||
// these lets, do they rely on anything between the top and here?
|
||||
// if not could they be put in the let list at the beginning?
|
||||
let hasGtPin = false;
|
||||
|
||||
let inversionAlpha = "DD";
|
||||
let row = "#000000";
|
||||
let bold = "#000000;font-weight: bold;";
|
||||
let unconf = "background-clip:padding-box;box-shadow: 0 0 7px 3px inset ";
|
||||
let layeredAlpha = "77";
|
||||
let layeredInversionAlpha = "66";
|
||||
let layeredUnconf = "background-clip:padding-box;box-shadow: 0 0 4px 2px inset ";
|
||||
let layeredUnconfAlpha = "AA";
|
||||
|
||||
// TODO: Hunting results might be used to filter, based on the "Callsigns: Only Wanted" option,
|
||||
// so maybe we can move this loop first, and add a check to the filtering loop?
|
||||
|
||||
// Second loop, hunting and highlighting
|
||||
for (let callHash in callRoster)
|
||||
{
|
||||
let entry = callRoster[callHash];
|
||||
let callObj = entry.callObj;
|
||||
|
||||
// Special case check for called station
|
||||
if (callObj.qrz == true && entry.tx == false)
|
||||
{
|
||||
// The instance has to be enabled
|
||||
if (window.opener.g_instances[callObj.instance].crEnable == true)
|
||||
{
|
||||
// Calling us, but we wouldn't normally display
|
||||
// If they are not ignored or we're in a QSO with them, let it through
|
||||
|
||||
// TODO: This is here because it's after the filtering stage
|
||||
if ((!(entry.DEcall in g_blockedCalls) && !(callObj.dxcc in g_blockedDxcc)) ||
|
||||
window.opener.g_instances[callObj.instance].status.DXcall == entry.DEcall)
|
||||
{
|
||||
entry.tx = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only render entries with `tx == true`, ignore the rest
|
||||
if (callObj.dxcc != -1 && entry.tx == true)
|
||||
{
|
||||
// In layered mode ("Hunting: mixed") the workHashSuffix becomes a more stricter 'live band',
|
||||
// while the layered suffix is a broader 'mixed band'
|
||||
let workHashSuffix, layeredHashSuffix;
|
||||
if (rosterSettings.layeredMode)
|
||||
{
|
||||
workHashSuffix = hashMaker("", callObj, rosterSettings.layeredMode);
|
||||
layeredHashSuffix = hashMaker("", callObj, g_rosterSettings.reference);
|
||||
}
|
||||
else
|
||||
{
|
||||
workHashSuffix = hashMaker("", callObj, g_rosterSettings.reference);
|
||||
layeredHashSuffix = false
|
||||
}
|
||||
let workHash = workHashSuffix; // TODO: Remove after replacing all occurrences with Suffix
|
||||
|
||||
let callsign = entry.DEcall;
|
||||
|
||||
callObj.hunting = {}
|
||||
callObj.callFlags = {}
|
||||
|
||||
let colorObject = Object();
|
||||
|
||||
let callPointer = callObj.CQ == true ? "cursor:pointer" : "";
|
||||
|
||||
let didWork = false;
|
||||
|
||||
let call = "#FFFF00";
|
||||
let grid = "#00FFFF";
|
||||
let calling = "#90EE90";
|
||||
let dxcc = "#FFA500";
|
||||
let state = "#90EE90";
|
||||
let cnty = "#CCDD00";
|
||||
let cont = "#00DDDD";
|
||||
let cqz = "#DDDDDD";
|
||||
let ituz = "#DDDDDD";
|
||||
let wpx = "#FFFF00";
|
||||
|
||||
hasGtPin = false;
|
||||
let shouldAlert = false;
|
||||
let callBg, gridBg, callingBg, dxccBg, stateBg, cntyBg, contBg, cqzBg, ituzBg, wpxBg, gtBg;
|
||||
let callConf, gridConf, callingConf, dxccConf, stateConf, cntyConf, contConf, cqzConf, ituzConf, wpxConf;
|
||||
|
||||
callBg = gridBg = callingBg = dxccBg = stateBg = cntyBg = contBg = cqzBg = ituzBg = wpxBg = gtBg = row;
|
||||
|
||||
callConf = gridConf = callingConf = dxccConf = stateConf = cntyConf = contConf = cqzConf = ituzConf = wpxConf =
|
||||
"";
|
||||
|
||||
let hash = callsign + workHashSuffix;
|
||||
let layeredHash = layeredHashSuffix && (callsign + layeredHashSuffix)
|
||||
|
||||
// Call worked in current logbook settings, regardless of hunting mode
|
||||
if (hash in g_worked.call)
|
||||
{
|
||||
callObj.callFlags.worked = true;
|
||||
didWork = true;
|
||||
callConf = `${unconf}${call}${inversionAlpha};`;
|
||||
|
||||
if (hash in g_confirmed.call)
|
||||
{
|
||||
callObj.callFlags.confirmed = true;
|
||||
callPointer = "text-decoration: line-through; ";
|
||||
callConf = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Calls that have OAMS chat support
|
||||
if (
|
||||
callsign in window.opener.g_gtCallsigns &&
|
||||
window.opener.g_gtCallsigns[callsign] in window.opener.g_gtFlagPins &&
|
||||
window.opener.g_gtFlagPins[window.opener.g_gtCallsigns[callsign]].canmsg == true
|
||||
)
|
||||
{
|
||||
callObj.callFlags.oams = true;
|
||||
// grab the CID
|
||||
callObj.gt = window.opener.g_gtCallsigns[callsign];
|
||||
hasGtPin = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.gt = 0;
|
||||
}
|
||||
|
||||
// We only do hunt highlighting when showing all entries
|
||||
// This means "Callsigns: All Traffic", "Callsigns: All Traffic/Only Wanted" and "Logbook: Award Tracker"
|
||||
// There is no highlighting in other modes
|
||||
if (rosterSettings.callMode == "all")
|
||||
{
|
||||
// Skip when "only new calls"
|
||||
// Questions: Move to the first loop? Why only skip new calls in "all traffic" and not other modes?
|
||||
if (allOnlyNew.checked == true && didWork && callObj.qrz == false)
|
||||
{
|
||||
entry.tx = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Hunting for callsigns
|
||||
if (huntCallsign.checked == true)
|
||||
{
|
||||
let hash = callsign + workHashSuffix;
|
||||
let layeredHash = rosterSettings.layeredMode && (callsign + layeredHashSuffix)
|
||||
|
||||
if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.call))
|
||||
{
|
||||
shouldAlert = true;
|
||||
|
||||
callObj.reason.push("call");
|
||||
|
||||
if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.call)
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.call)
|
||||
{
|
||||
callObj.hunting.call = "worked-and-mixed";
|
||||
callConf = `${layeredUnconf}${call}${layeredUnconfAlpha};`;
|
||||
callBg = `${call}${layeredInversionAlpha}`;
|
||||
call = bold;
|
||||
}
|
||||
// /* Currently we don't have a way to figure out
|
||||
// * if the call is worked only in this band or also others,
|
||||
// * so we cannot cover this particular combination
|
||||
// * and have to default to just showing it as plain "worked"
|
||||
// */
|
||||
// else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.call)
|
||||
// {
|
||||
// callObj.hunting.call = "worked-and-mixed-worked";
|
||||
// callConf = `${layeredUnconf}${call}${layeredAlpha};`;
|
||||
// }
|
||||
else
|
||||
{
|
||||
callObj.hunting.call = "worked";
|
||||
callConf = `${unconf}${call}${inversionAlpha};`;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.call)
|
||||
{
|
||||
callObj.hunting.call = "mixed";
|
||||
callBg = `${call}${layeredAlpha};`;
|
||||
call = bold;
|
||||
}
|
||||
else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.call)
|
||||
{
|
||||
callObj.hunting.call = "mixed-worked";
|
||||
callConf = `${unconf}${call}${layeredAlpha};`;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.call = "hunted";
|
||||
callBg = `${call}${inversionAlpha};`;
|
||||
call = bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hunting for "stations calling you"
|
||||
if (huntQRZ.checked == true && callObj.qrz == true)
|
||||
{
|
||||
callObj.callFlags.calling = true
|
||||
shouldAlert = true;
|
||||
callObj.reason.push("qrz");
|
||||
}
|
||||
|
||||
// Hunting for stations with OAMS
|
||||
if (huntOAMS.checked == true && hasGtPin == true)
|
||||
{
|
||||
callObj.hunting.oams = "hunted";
|
||||
shouldAlert = true;
|
||||
callObj.reason.push("oams");
|
||||
}
|
||||
|
||||
// Hunting for grids
|
||||
if (huntGrid.checked == true && callObj.grid.length > 1)
|
||||
{
|
||||
let hash = callObj.grid.substr(0, 4) + workHashSuffix;
|
||||
let layeredHash = rosterSettings.layeredMode && (callObj.grid.substr(0, 4) + layeredHashSuffix)
|
||||
|
||||
if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.grid))
|
||||
{
|
||||
shouldAlert = true;
|
||||
|
||||
callObj.reason.push("grid");
|
||||
|
||||
if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.grid)
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.grid)
|
||||
{
|
||||
callObj.hunting.grid = "worked-and-mixed";
|
||||
gridConf = `${layeredUnconf}${grid}${layeredUnconfAlpha};`;
|
||||
gridBg = `${grid}${layeredInversionAlpha}`;
|
||||
grid = bold;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.grid = "worked";
|
||||
gridConf = `${unconf}${grid}${inversionAlpha};`;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.grid)
|
||||
{
|
||||
callObj.hunting.grid = "mixed";
|
||||
gridBg = `${grid}${layeredAlpha};`;
|
||||
grid = bold;
|
||||
}
|
||||
else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.grid)
|
||||
{
|
||||
callObj.hunting.grid = "mixed-worked";
|
||||
gridConf = `${unconf}${grid}${layeredAlpha};`;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.grid = "hunted";
|
||||
gridBg = `${grid}${inversionAlpha};`;
|
||||
grid = bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hunting for DXCC
|
||||
if (huntDXCC.checked == true)
|
||||
{
|
||||
let hash = String(callObj.dxcc) + workHashSuffix;
|
||||
let layeredHash = rosterSettings.layeredMode && (String(callObj.dxcc) + layeredHashSuffix)
|
||||
|
||||
if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.dxcc))
|
||||
{
|
||||
shouldAlert = true;
|
||||
|
||||
callObj.reason.push("dxcc");
|
||||
|
||||
if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.dxcc)
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.dxcc)
|
||||
{
|
||||
callObj.hunting.dxcc = "worked-and-mixed";
|
||||
dxccConf = `${layeredUnconf}${dxcc}${layeredUnconfAlpha};`;
|
||||
dxccBg = `${dxcc}${layeredInversionAlpha}`;
|
||||
dxcc = bold;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.dxcc = "worked";
|
||||
dxccConf = `${unconf}${dxcc}${inversionAlpha};`;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.dxcc)
|
||||
{
|
||||
callObj.hunting.dxcc = "mixed";
|
||||
dxccBg = `${dxcc}${layeredAlpha};`;
|
||||
dxcc = bold;
|
||||
}
|
||||
else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.dxcc)
|
||||
{
|
||||
callObj.hunting.dxcc = "mixed-worked";
|
||||
dxccConf = `${unconf}${dxcc}${layeredAlpha};`;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.dxcc = "hunted";
|
||||
dxccBg = `${dxcc}${inversionAlpha};`;
|
||||
dxcc = bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hunting for US States
|
||||
if (huntState.checked == true && window.opener.g_callsignLookups.ulsUseEnable == true)
|
||||
{
|
||||
let stateSearch = callObj.state;
|
||||
let finalDxcc = callObj.dxcc;
|
||||
if (finalDxcc == 291 || finalDxcc == 110 || finalDxcc == 6)
|
||||
{
|
||||
if (stateSearch in window.opener.g_StateData)
|
||||
{
|
||||
let hash = stateSearch + workHashSuffix;
|
||||
let layeredHash = rosterSettings.layeredMode && (stateSearch + layeredHashSuffix)
|
||||
|
||||
if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.state))
|
||||
{
|
||||
shouldAlert = true;
|
||||
|
||||
callObj.reason.push("state");
|
||||
|
||||
if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.state)
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.state)
|
||||
{
|
||||
callObj.hunting.state = "worked-and-mixed";
|
||||
stateConf = `${layeredUnconf}${state}${layeredUnconfAlpha};`;
|
||||
stateBg = `${state}${layeredInversionAlpha}`;
|
||||
state = bold;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.state = "worked";
|
||||
stateConf = `${unconf}${state}${inversionAlpha};`;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.state)
|
||||
{
|
||||
callObj.hunting.state = "mixed";
|
||||
stateBg = `${state}${layeredAlpha};`;
|
||||
state = bold;
|
||||
}
|
||||
else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.state)
|
||||
{
|
||||
callObj.hunting.state = "mixed-worked";
|
||||
stateConf = `${unconf}${state}${layeredAlpha};`;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.state = "hunted";
|
||||
stateBg = `${state}${inversionAlpha};`;
|
||||
state = bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hunting for US Counties
|
||||
if (huntCounty.checked == true && window.opener.g_callsignLookups.ulsUseEnable == true)
|
||||
{
|
||||
let finalDxcc = callObj.dxcc;
|
||||
if (
|
||||
callObj.cnty &&
|
||||
(finalDxcc == 291 || finalDxcc == 110 || finalDxcc == 6 || finalDxcc == 202) &&
|
||||
callObj.cnty.length > 0
|
||||
)
|
||||
{
|
||||
let hash = callObj.cnty + (rosterSettings.layeredMode ? layeredHashSuffix : workHashSuffix);
|
||||
|
||||
if ((rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.cnty)) || callObj.qual == false)
|
||||
{
|
||||
if (callObj.qual == false)
|
||||
{
|
||||
let counties = window.opener.g_zipToCounty[callObj.zipcode];
|
||||
let foundHit = false;
|
||||
for (let cnt in counties)
|
||||
{
|
||||
let hh = counties[cnt] + workHash;
|
||||
callObj.cnty = counties[cnt];
|
||||
if (rosterSettings.huntIndex && !(hh in rosterSettings.huntIndex.cnty))
|
||||
{
|
||||
foundHit = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (foundHit) shouldAlert = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
shouldAlert = true;
|
||||
}
|
||||
|
||||
if (shouldAlert)
|
||||
{
|
||||
callObj.reason.push("cnty");
|
||||
|
||||
if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.cnty)
|
||||
{
|
||||
callObj.hunting.cnty = "worked";
|
||||
cntyConf = `${unconf}${cnty}${inversionAlpha};`;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.cnty = "hunted";
|
||||
cntyBg = `${cnty}${inversionAlpha}`;
|
||||
cnty = bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hunting for CQ Zones
|
||||
if (huntCQz.checked == true)
|
||||
{
|
||||
let huntTotal = callObj.cqza.length;
|
||||
let huntFound = 0, layeredFound = 0, workedFound = 0, layeredWorkedFound = 0;
|
||||
|
||||
for (index in callObj.cqza)
|
||||
{
|
||||
let hash = callObj.cqza[index] + workHashSuffix;
|
||||
let layeredHash = rosterSettings.layeredMode && (callObj.cqza[index] + layeredHashSuffix)
|
||||
|
||||
if (rosterSettings.huntIndex && hash in rosterSettings.huntIndex.cqz) huntFound++;
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.cqz) layeredFound++;
|
||||
if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.cqz) workedFound++;
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.cqz) layeredWorkedFound++;
|
||||
}
|
||||
if (huntFound != huntTotal)
|
||||
{
|
||||
shouldAlert = true;
|
||||
callObj.reason.push("cqz");
|
||||
|
||||
if (rosterSettings.workedIndex && workedFound == huntTotal)
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredFound == huntTotal)
|
||||
{
|
||||
callObj.hunting.cqz = "worked-and-mixed";
|
||||
cqzConf = `${layeredUnconf}${cqz}${layeredUnconfAlpha};`;
|
||||
cqzBg = `${cqz}${layeredInversionAlpha}`;
|
||||
cqz = bold;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.cqz = "worked";
|
||||
cqzConf = `${unconf}${cqz}${inversionAlpha};`;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredFound == huntTotal)
|
||||
{
|
||||
callObj.hunting.cqz = "mixed";
|
||||
cqzBg = `${cqz}${layeredAlpha};`;
|
||||
cqz = bold;
|
||||
}
|
||||
else if (rosterSettings.layeredMode && layeredWorkedFound == huntTotal)
|
||||
{
|
||||
callObj.hunting.cqz = "mixed-worked";
|
||||
cqzConf = `${unconf}${cqz}${layeredAlpha};`;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.cqz = "hunted";
|
||||
cqzBg = `${cqz}${inversionAlpha};`;
|
||||
cqz = bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hunting for ITU Zones
|
||||
if (huntITUz.checked == true)
|
||||
{
|
||||
let huntTotal = callObj.ituza.length;
|
||||
let huntFound = 0, layeredFound = 0, workedFound = 0, layeredWorkedFound = 0;
|
||||
|
||||
for (index in callObj.ituza)
|
||||
{
|
||||
let hash = callObj.ituza[index] + workHashSuffix;
|
||||
let layeredHash = rosterSettings.layeredMode && (callObj.ituza[index] + layeredHashSuffix)
|
||||
|
||||
if (rosterSettings.huntIndex && hash in rosterSettings.huntIndex.ituz) huntFound++;
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.ituz) layeredFound++;
|
||||
if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.ituz) workedFound++;
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.ituz) layeredWorkedFound++;
|
||||
}
|
||||
if (huntFound != huntTotal)
|
||||
{
|
||||
shouldAlert = true;
|
||||
callObj.reason.push("ituz");
|
||||
|
||||
if (rosterSettings.workedIndex && workedFound == huntTotal)
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredFound == huntTotal)
|
||||
{
|
||||
callObj.hunting.ituz = "worked-and-mixed";
|
||||
ituzConf = `${layeredUnconf}${ituz}${layeredUnconfAlpha};`;
|
||||
ituzBg = `${ituz}${layeredInversionAlpha}`;
|
||||
ituz = bold;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.ituz = "worked";
|
||||
ituzConf = `${unconf}${ituz}${inversionAlpha};`;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredFound == huntTotal)
|
||||
{
|
||||
callObj.hunting.ituz = "mixed";
|
||||
ituzBg = `${ituz}${layeredAlpha};`;
|
||||
ituz = bold;
|
||||
}
|
||||
else if (rosterSettings.layeredMode && layeredWorkedFound == huntTotal)
|
||||
{
|
||||
callObj.hunting.ituz = "mixed-worked";
|
||||
ituzConf = `${unconf}${ituz}${layeredAlpha};`;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.ituz = "hunted";
|
||||
ituzBg = `${ituz}${inversionAlpha};`;
|
||||
ituz = bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hunting for WPX (Prefixes)
|
||||
if (huntPX.checked == true && callObj.px)
|
||||
{
|
||||
let hash = String(callObj.px) + workHashSuffix;
|
||||
let layeredHash = rosterSettings.layeredMode && (String(callObj.px) + layeredHashSuffix)
|
||||
|
||||
if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.px))
|
||||
{
|
||||
shouldAlert = true;
|
||||
|
||||
callObj.reason.push("wpx");
|
||||
|
||||
if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.px)
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.px)
|
||||
{
|
||||
callObj.hunting.wpx = "worked-and-mixed";
|
||||
wpxConf = `${layeredUnconf}${wpx}${layeredUnconfAlpha};`;
|
||||
wpxBg = `${wpx}${layeredInversionAlpha}`;
|
||||
wpx = bold;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.wpx = "worked";
|
||||
wpxConf = `${unconf}${wpx}${inversionAlpha};`;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.px)
|
||||
{
|
||||
callObj.hunting.wpx = "mixed";
|
||||
wpxBg = `${wpx}${layeredAlpha};`;
|
||||
wpx = bold;
|
||||
}
|
||||
else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.px)
|
||||
{
|
||||
callObj.hunting.wpx = "mixed-worked";
|
||||
wpxConf = `${unconf}${wpx}${layeredAlpha};`;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.wpx = "hunted";
|
||||
wpxBg = `${wpx}${inversionAlpha};`;
|
||||
wpx = bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hunting for Continents
|
||||
if (huntCont.checked == true && callObj.cont)
|
||||
{
|
||||
let hash = String(callObj.cont) + workHashSuffix;
|
||||
let layeredHash = rosterSettings.layeredMode && (String(callObj.cont) + layeredHashSuffix)
|
||||
|
||||
if (rosterSettings.huntIndex && !(hash in rosterSettings.huntIndex.cont))
|
||||
{
|
||||
shouldAlert = true;
|
||||
|
||||
callObj.reason.push("cont");
|
||||
|
||||
if (rosterSettings.workedIndex && hash in rosterSettings.workedIndex.cont)
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.cont)
|
||||
{
|
||||
callObj.hunting.cont = "worked-and-mixed";
|
||||
contConf = `${layeredUnconf}${cont}${layeredUnconfAlpha};`;
|
||||
contBg = `${cont}${layeredInversionAlpha}`;
|
||||
cont = bold;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.cont = "worked";
|
||||
contConf = `${unconf}${cont}${inversionAlpha};`;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rosterSettings.layeredMode && layeredHash in rosterSettings.huntIndex.cont)
|
||||
{
|
||||
callObj.hunting.cont = "mixed";
|
||||
contBg = `${cont}${layeredAlpha};`;
|
||||
cont = bold;
|
||||
}
|
||||
else if (rosterSettings.layeredMode && layeredHash in rosterSettings.workedIndex.cont)
|
||||
{
|
||||
callObj.hunting.cont = "mixed-worked";
|
||||
contConf = `${unconf}${cont}${layeredAlpha};`;
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.hunting.cont = "hunted";
|
||||
contBg = `${cont}${inversionAlpha};`;
|
||||
cont = bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Station is calling us
|
||||
if (callObj.DXcall == window.opener.myDEcall)
|
||||
{
|
||||
callingBg = "#0000FF" + inversionAlpha;
|
||||
calling = "#FFFF00;text-shadow: 0px 0px 2px #FFFF00";
|
||||
}
|
||||
else if (callObj.CQ == true && !g_rosterSettings.cqOnly)
|
||||
{
|
||||
callingBg = calling + inversionAlpha;
|
||||
calling = bold;
|
||||
}
|
||||
|
||||
// Assemble all styles
|
||||
colorObject.call = "style='" + callConf + "background-color:" + callBg + ";color:" +
|
||||
call + ";" + callPointer + "'";
|
||||
colorObject.grid = "style='" + gridConf + "background-color:" + gridBg + ";color:" + grid + ";cursor:pointer'";
|
||||
colorObject.calling = "style='" + callingConf + "background-color:" + callingBg + ";color:" + calling + "'";
|
||||
colorObject.dxcc = "style='" + dxccConf + "background-color:" + dxccBg + ";color:" + dxcc + "'";
|
||||
colorObject.state = "style='" + stateConf + "background-color:" + stateBg + ";color:" + state + "'";
|
||||
colorObject.cnty = "style='" + cntyConf + "background-color:" + cntyBg + ";color:" + cnty + "'";
|
||||
colorObject.cont = "style='" + contConf + "background-color:" + contBg + ";color:" + cont + "'";
|
||||
colorObject.cqz = "style='" + cqzConf + "background-color:" + cqzBg + ";color:" + cqz + "'";
|
||||
colorObject.ituz = "style='" + ituzConf + "background-color:" + ituzBg + ";color:" + ituz + "'";
|
||||
colorObject.px = "style='" + wpxConf + "background-color:" + wpxBg + ";color:" + wpx + "'";
|
||||
|
||||
// Just in case, don't alert if we worked this callsign alread
|
||||
if (didWork && shouldAlert) shouldAlert = false;
|
||||
|
||||
callObj.shouldAlert = shouldAlert;
|
||||
|
||||
callObj.style = colorObject;
|
||||
|
||||
if (g_rosterSettings.columns.Spot)
|
||||
{
|
||||
callObj.spot = window.opener.getSpotTime(
|
||||
callObj.DEcall + callObj.mode + callObj.band + callObj.grid
|
||||
);
|
||||
if (callObj.spot == null)
|
||||
{
|
||||
callObj.spot = { when: 0, snr: 0 };
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.spot = { when: 0, snr: 0 };
|
||||
}
|
||||
|
||||
rosterSettings.modes[callObj.mode] = true;
|
||||
rosterSettings.bands[callObj.band] = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
function renderCompactRosterHeaders()
|
||||
{
|
||||
return "<div id=\"buttonsDiv\" style=\"margin-left:0px;white-space:normal;\">";
|
||||
}
|
||||
|
||||
function renderCompactRosterRow(callObj)
|
||||
{
|
||||
var thisCall = callObj.DEcall;
|
||||
var tt =
|
||||
callObj.RSTsent +
|
||||
"㏈, " +
|
||||
parseInt(callObj.dt * 100) +
|
||||
"ms, " +
|
||||
callObj.delta +
|
||||
"hz" +
|
||||
(callObj.grid.length ? ", " + callObj.grid : "") +
|
||||
", " +
|
||||
(timeNowSec() - callObj.age).toDHMS();
|
||||
var worker =
|
||||
"<div class='compact' onClick='initiateQso(\"" +
|
||||
thisCall +
|
||||
callObj.band +
|
||||
callObj.mode +
|
||||
"\")' ";
|
||||
worker +=
|
||||
"id='" +
|
||||
thisCall +
|
||||
callObj.band +
|
||||
callObj.mode +
|
||||
"' title='" +
|
||||
tt +
|
||||
"'>";
|
||||
worker +=
|
||||
"<div class='compactCallsign' name='Callsign' " +
|
||||
callObj.style.call +
|
||||
" >" +
|
||||
thisCall.formatCallsign() +
|
||||
"</div>";
|
||||
worker +=
|
||||
"<div class='compactDXCC' name='DXCC (" +
|
||||
callObj.dxcc +
|
||||
")' " +
|
||||
callObj.style.dxcc +
|
||||
">" +
|
||||
window.opener.g_dxccToAltName[callObj.dxcc] +
|
||||
"</div>";
|
||||
worker += "</div>";
|
||||
|
||||
return worker;
|
||||
}
|
||||
|
||||
function renderCompactRosterFooter()
|
||||
{
|
||||
return "</div>";
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
function renderNormalRosterHeaders(columns)
|
||||
{
|
||||
let html = "<table id='callTable' class='rosterTable' align=left><thead>"
|
||||
html = html + columns.map(column => renderHeaderForColumn(column)).join("\n")
|
||||
html = html + "</thead><tbody>"
|
||||
|
||||
return html
|
||||
}
|
||||
|
||||
function renderNormalRosterRow(columns, callObj)
|
||||
{
|
||||
callObj.grid4 = callObj.grid4 || (callObj.grid && callObj.grid.length > 1) ? callObj.grid.substr(0, 4) : "-";
|
||||
callObj.hash = callObj.hash || `${callObj.DEcall}${callObj.band}${callObj.mode}`;
|
||||
|
||||
let html = `<tr id='${callObj.hash}'>`;
|
||||
|
||||
html = html + columns.map(column => renderEntryForColumn(column, callObj)).join("\n")
|
||||
|
||||
html += "</tr>";
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
function renderNormalRosterFooter()
|
||||
{
|
||||
return "</tbody></table>";
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
function renderRoster(callRoster, rosterSettings)
|
||||
{
|
||||
let columnOverrides = {
|
||||
Callsign: true,
|
||||
Grid: true
|
||||
}
|
||||
|
||||
if (window.opener.g_callsignLookups.eqslUseEnable == true)
|
||||
{
|
||||
useseQSLDiv.style.display = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
columnOverrides.eQSL = false;
|
||||
useseQSLDiv.style.display = "none";
|
||||
}
|
||||
|
||||
if (window.opener.g_callsignLookups.oqrsUseEnable == true)
|
||||
{
|
||||
usesOQRSDiv.style.display = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
columnOverrides.OQRS = false;
|
||||
usesOQRSDiv.style.display = "none";
|
||||
}
|
||||
|
||||
if (window.opener.g_callsignLookups.lotwUseEnable == true)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
else
|
||||
{
|
||||
columnOverrides.LoTW = false;
|
||||
}
|
||||
|
||||
// dealing with spots
|
||||
if (g_rosterSettings.columns.Spot == true) onlySpotDiv.style.display = "";
|
||||
else onlySpotDiv.style.display = "none";
|
||||
|
||||
// callmode (all or only new)
|
||||
if (rosterSettings.callMode == "all") allOnlyNewDiv.style.display = "";
|
||||
else allOnlyNewDiv.style.display = "none";
|
||||
|
||||
// Show the roster count in the window title
|
||||
|
||||
// let visibleCallList = callRoster.filter(entry => entry.tx);
|
||||
|
||||
let visibleCallList = [];
|
||||
let band =
|
||||
window.opener.g_appSettings.gtBandFilter == "auto"
|
||||
? window.opener.g_appSettings.myBand
|
||||
: window.opener.g_appSettings.gtBandFilter.length == 0
|
||||
? ""
|
||||
: window.opener.g_appSettings.gtBandFilter;
|
||||
for (entry in callRoster)
|
||||
{
|
||||
// entry should populate in general
|
||||
if (callRoster[entry].tx)
|
||||
{
|
||||
// check setting for call roster clear on band change.
|
||||
// if true and band is current band, populate
|
||||
if (window.opener.g_appSettings.clearRosterOnBandChange)
|
||||
{
|
||||
if (callRoster[entry].callObj.band == band)
|
||||
{
|
||||
visibleCallList.push(callRoster[entry]);
|
||||
}
|
||||
}
|
||||
else if (!window.opener.g_appSettings.clearRosterOnBandChange)
|
||||
{
|
||||
visibleCallList.push(callRoster[entry]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let totalCount = Object.keys(callRoster).length;
|
||||
let visibleCount = visibleCallList.length;
|
||||
let huntedCount = visibleCallList.filter(obj => Object.keys(obj.callObj.hunting).length > 0).length
|
||||
let countParts = [];
|
||||
|
||||
if (totalCount != visibleCount)
|
||||
{
|
||||
countParts.push(`${totalCount} heard`);
|
||||
}
|
||||
|
||||
countParts.push(`${visibleCount} in roster`);
|
||||
|
||||
if (huntedCount != visibleCount)
|
||||
{
|
||||
countParts.push(`${huntedCount} wanted`);
|
||||
}
|
||||
|
||||
window.document.title = `Call Roster: ${countParts.join(" • ")}`;
|
||||
|
||||
if (g_rosterSettings.compact)
|
||||
{
|
||||
sortCallList(visibleCallList, "Age", false);
|
||||
}
|
||||
else
|
||||
{
|
||||
sortCallList(visibleCallList, g_rosterSettings.sortColumn, g_rosterSettings.sortReverse);
|
||||
}
|
||||
|
||||
let showBands = (Object.keys(rosterSettings.bands).length > 1) || g_rosterSettings.columns.Band;
|
||||
let showModes = (Object.keys(rosterSettings.modes).length > 1) || g_rosterSettings.columns.Mode;
|
||||
|
||||
columnOverrides.Band = showBands
|
||||
columnOverrides.Mode = showModes
|
||||
const rosterColumns = rosterColumnList(g_rosterSettings.columns, columnOverrides)
|
||||
|
||||
let worker = g_rosterSettings.compact ? renderCompactRosterHeaders() : renderNormalRosterHeaders(rosterColumns)
|
||||
|
||||
// Third loop: render all rows
|
||||
for (let x in visibleCallList)
|
||||
{
|
||||
let callObj = visibleCallList[x].callObj;
|
||||
|
||||
// TODO: This is filtering
|
||||
if (callObj.shouldAlert == false && rosterSettings.onlyHits == true && callObj.qrz == false)
|
||||
{ continue; }
|
||||
|
||||
if (callObj.DEcall.match("^[A-Z][0-9][A-Z](/w+)?$"))
|
||||
{ callObj.style.call = "class='oneByOne'"; }
|
||||
if (callObj.DEcall == window.opener.g_instances[callObj.instance].status.DXcall)
|
||||
{
|
||||
if (window.opener.g_instances[callObj.instance].status.TxEnabled == 1)
|
||||
{
|
||||
callObj.style.call = "class='dxCalling'";
|
||||
}
|
||||
else
|
||||
{
|
||||
callObj.style.call = "class='dxCaller'";
|
||||
}
|
||||
}
|
||||
|
||||
worker += g_rosterSettings.compact ? renderCompactRosterRow(callObj) : renderNormalRosterRow(rosterColumns, callObj)
|
||||
}
|
||||
|
||||
worker += g_rosterSettings.compact ? renderCompactRosterFooter() : renderNormalRosterFooter()
|
||||
RosterTable.innerHTML = worker;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
function rosterColumnList(settings = {}, overrides = {})
|
||||
{
|
||||
return g_rosterSettings.columnOrder.filter(column =>
|
||||
{
|
||||
return column && (settings[column] || overrides[column]) && !(overrides[column] === false)
|
||||
})
|
||||
}
|
||||
|
||||
function renderHeaderForColumn(column)
|
||||
{
|
||||
const columnInfo = ROSTER_COLUMNS[column]
|
||||
|
||||
let attrs = (columnInfo && columnInfo.tableHeader && columnInfo.tableHeader()) || {}
|
||||
|
||||
attrs.html = attrs.html || column
|
||||
|
||||
if (columnInfo.compare)
|
||||
{
|
||||
attrs.style = "cursor: pointer"
|
||||
attrs.onClick = `setRosterSorting('${column}');`
|
||||
}
|
||||
|
||||
return renderRosterTableHTML("th", attrs)
|
||||
}
|
||||
|
||||
function renderEntryForColumn(column, entry)
|
||||
{
|
||||
const columnInfo = ROSTER_COLUMNS[column]
|
||||
|
||||
let attrs = (columnInfo && columnInfo.tableData && columnInfo.tableData(entry)) || {}
|
||||
|
||||
return renderRosterTableHTML("td", attrs)
|
||||
}
|
||||
|
||||
function renderRosterTableHTML(tag, attrs)
|
||||
{
|
||||
let innerHtml = attrs.html || ""
|
||||
delete attrs.html
|
||||
|
||||
let rawAttrs = attrs.rawAttrs || ""
|
||||
delete attrs.rawAttrs
|
||||
|
||||
let attrEntries = Object.entries(attrs).filter(kv => !!kv[1])
|
||||
|
||||
return `<${tag} ${rawAttrs} ${attrEntries.map((kv) => `${kv[0]}="${kv[1].replace(/"/g, """)}"`).join(" ")}>${innerHtml}</${tag}>`
|
||||
}
|
||||
|
||||
function setRosterSorting(column)
|
||||
{
|
||||
if (g_rosterSettings.sortColumn === column)
|
||||
{
|
||||
g_rosterSettings.sortReverse = !g_rosterSettings.sortReverse
|
||||
}
|
||||
else
|
||||
{
|
||||
g_rosterSettings.sortColumn = column
|
||||
g_rosterSettings.sortReverse = false
|
||||
}
|
||||
|
||||
writeRosterSettings();
|
||||
|
||||
window.opener.goProcessRoster();
|
||||
}
|
||||
|
||||
function sortCallList(callList, sortColumn, sortReverse)
|
||||
{
|
||||
const columnInfo = ROSTER_COLUMNS[sortColumn]
|
||||
|
||||
callList.sort((columnInfo && columnInfo.compare) || ROSTER_COLUMNS.Age.compare)
|
||||
|
||||
if (sortReverse)
|
||||
{
|
||||
callList.reverse()
|
||||
}
|
||||
}
|
||||
|
||||
function validateRosterColumnOrder(columns)
|
||||
{
|
||||
let correctedColumnOrder = (columns || DEFAULT_COLUMN_ORDER || []).slice();
|
||||
|
||||
DEFAULT_COLUMN_ORDER.forEach(column =>
|
||||
{
|
||||
if (!correctedColumnOrder.includes(column)) correctedColumnOrder.push(column);
|
||||
})
|
||||
correctedColumnOrder = correctedColumnOrder.filter(column => !!ROSTER_COLUMNS[column])
|
||||
|
||||
return correctedColumnOrder;
|
||||
}
|
||||
|
||||
function changeRosterColumnOrder(columns)
|
||||
{
|
||||
g_rosterSettings.columnOrder = validateRosterColumnOrder(columns);
|
||||
writeRosterSettings();
|
||||
window.opener.goProcessRoster();
|
||||
}
|
|
@ -0,0 +1,378 @@
|
|||
const DEFAULT_COLUMN_ORDER = [
|
||||
"Callsign", "Band", "Mode", "Grid", "Calling", "Msg",
|
||||
"DXCC", "Flag", "State", "County", "Cont",
|
||||
"dB", "Freq", "DT", "Dist", "Azim",
|
||||
"CQz", "ITUz", "PX",
|
||||
"LoTW", "eQSL", "OQRS",
|
||||
"Life", "Spot", "OAMS", "Age"
|
||||
]
|
||||
|
||||
const LEGACY_COLUMN_SORT_ID = {
|
||||
0: "Callsign",
|
||||
1: "Grid",
|
||||
2: "dB",
|
||||
3: "DT",
|
||||
4: "Freq",
|
||||
5: "DXCC",
|
||||
7: "Dist",
|
||||
8: "Azim",
|
||||
9: "State",
|
||||
10: "Calling",
|
||||
11: "PX",
|
||||
12: "Life",
|
||||
13: "Spot",
|
||||
14: "OAMS",
|
||||
15: "County",
|
||||
16: "Cont"
|
||||
}
|
||||
|
||||
const getterSimpleComparer = (getter) => (a, b) =>
|
||||
{
|
||||
const aVal = getter(a);
|
||||
const bVal = getter(b);
|
||||
if (aVal == null) return 1;
|
||||
if (bVal == null) return -1;
|
||||
if (aVal > bVal) return 1;
|
||||
if (aVal < bVal) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const callObjSimpleComparer = (attr) => getterSimpleComparer((elem) => elem.callObj[attr])
|
||||
|
||||
const callObjLocaleComparer = (attr) => (a, b) =>
|
||||
{
|
||||
if (a.callObj[attr] == null) return 1;
|
||||
if (b.callObj[attr] == null) return -1;
|
||||
return a.callObj[attr].localeCompare(b.callObj[attr]);
|
||||
}
|
||||
|
||||
const ROSTER_COLUMNS = {
|
||||
|
||||
Callsign: {
|
||||
compare: callObjLocaleComparer("DEcall"),
|
||||
tableHeader: () => ({ align: "left" }),
|
||||
tableData: (callObj) =>
|
||||
{
|
||||
let attrs = {
|
||||
title: callObj.awardReason,
|
||||
name: "Callsign",
|
||||
align: "left",
|
||||
onClick: `initiateQso("${callObj.hash}")`,
|
||||
rawAttrs: callObj.style.call,
|
||||
html: html = callObj.DEcall.formatCallsign()
|
||||
}
|
||||
|
||||
let acks = window.opener.g_acknowledgedCalls;
|
||||
if (acks[callObj.DEcall])
|
||||
{
|
||||
attrs.html = `${attrs.html} <span class='acknowledged'><img class='ackBadge' src='${acks[callObj.DEcall].badge}'></span>`
|
||||
attrs.title = `${attrs.title} - ${acks[callObj.DEcall].message}`
|
||||
}
|
||||
|
||||
return attrs
|
||||
}
|
||||
},
|
||||
|
||||
Band: {
|
||||
compare: false,
|
||||
tableData: (callObj) => ({
|
||||
style: `color: #${window.opener.g_pskColors[callObj.band]};`,
|
||||
html: callObj.band
|
||||
})
|
||||
},
|
||||
|
||||
Mode: {
|
||||
compare: false,
|
||||
tableData: (callObj) => ({
|
||||
style: `color: #${g_modeColors[callObj.mode] || "888888"};`,
|
||||
html: callObj.mode
|
||||
})
|
||||
},
|
||||
|
||||
Grid: {
|
||||
compare: callObjSimpleComparer("grid"),
|
||||
tableData: (callObj) => ({
|
||||
rawAttrs: callObj.style.grid,
|
||||
onClick: `centerOn("${callObj.grid4}")`,
|
||||
html: callObj.grid4
|
||||
})
|
||||
},
|
||||
|
||||
Calling: {
|
||||
compare: callObjLocaleComparer("DXcall"),
|
||||
tableData: (callObj) => ({
|
||||
rawAttrs: callObj.style.calling,
|
||||
name: callObj.CQ ? "CQ" : "Calling",
|
||||
html: callObj.DXcall.formatCallsign()
|
||||
})
|
||||
},
|
||||
|
||||
Msg: {
|
||||
compare: callObjLocaleComparer("DXcall"),
|
||||
tableData: (callObj) => ({ html: callObj.msg })
|
||||
},
|
||||
|
||||
DXCC: {
|
||||
compare: (a, b) => window.opener.myDxccCompare(a.callObj, b.callObj),
|
||||
tableData: (callObj) => ({
|
||||
title: window.opener.g_worldGeoData[window.opener.g_dxccToGeoData[callObj.dxcc]].pp,
|
||||
name: `DXCC (${callObj.dxcc})`,
|
||||
rawAttrs: callObj.style.dxcc,
|
||||
html: window.opener.g_dxccToAltName[callObj.dxcc]
|
||||
})
|
||||
},
|
||||
|
||||
Flag: {
|
||||
compare: (a, b) => window.opener.myDxccCompare(a.callObj, b.callObj),
|
||||
tableData: (callObj) => ({
|
||||
align: "center",
|
||||
style: "margin:0; padding:0;",
|
||||
html: `<img style='padding-top:3px' src='./img/flags/16/${window.opener.g_worldGeoData[window.opener.g_dxccToGeoData[callObj.dxcc]].flag}'>`
|
||||
})
|
||||
},
|
||||
|
||||
State: {
|
||||
compare: callObjSimpleComparer("state"),
|
||||
tableData: (callObj) => ({
|
||||
align: "center",
|
||||
rawAttrs: callObj.style.state,
|
||||
html: callObj.state ? callObj.state.substr(3) : ""
|
||||
})
|
||||
},
|
||||
|
||||
County: {
|
||||
// Not sure why this comparison uses substring, but this is what the original code did
|
||||
compare: getterSimpleComparer((elem) => elem.callObj.cnty && elem.callObj.cnty.substr(3)),
|
||||
tableData: (callObj) =>
|
||||
{
|
||||
let attrs = {
|
||||
align: "center",
|
||||
rawAttrs: callObj.style.cnty,
|
||||
html: callObj.cnty ? window.opener.g_cntyToCounty[callObj.cnty] : ""
|
||||
}
|
||||
if (callObj.cnty && callObj.qual)
|
||||
{
|
||||
attrs.title = "ZIP Code matches multiple counties, click to do a full lookup"
|
||||
attrs.onClick = `lookupZip("${callObj.DEcall}", "${callObj.grid4}")`
|
||||
attrs.html = `¿ ${attrs.html} ?`
|
||||
}
|
||||
return attrs
|
||||
}
|
||||
},
|
||||
|
||||
Cont: {
|
||||
compare: callObjSimpleComparer("cont"),
|
||||
tableData: (callObj) => ({
|
||||
align: "center",
|
||||
rawAttrs: callObj.style.cont,
|
||||
html: callObj.cont ? callObj.cont : ""
|
||||
})
|
||||
},
|
||||
|
||||
dB: {
|
||||
compare: callObjSimpleComparer("RSTsent"),
|
||||
tableData: (callObj) => ({
|
||||
style: "color:#DD44DD;",
|
||||
html: `<b>${callObj.RSTsent}</b>`
|
||||
})
|
||||
},
|
||||
|
||||
Freq: {
|
||||
compare: callObjSimpleComparer("delta"),
|
||||
tableData: (callObj) => ({
|
||||
style: "color: #00FF00;",
|
||||
html: callObj.delta
|
||||
})
|
||||
},
|
||||
|
||||
DT: {
|
||||
compare: callObjSimpleComparer("dt"),
|
||||
tableData: (callObj) => ({
|
||||
style: "color: #1E90FF;",
|
||||
html: callObj.dt
|
||||
})
|
||||
},
|
||||
|
||||
Dist: {
|
||||
compare: callObjSimpleComparer("distance"),
|
||||
tableHeader: () => ({ html: `Dist (${window.opener.distanceUnit.value.toLowerCase()})` }),
|
||||
tableData: (callObj) => ({
|
||||
style: "color: cyan;",
|
||||
html: Math.round(callObj.distance * MyCircle.validateRadius(window.opener.distanceUnit.value))
|
||||
})
|
||||
},
|
||||
|
||||
Azim: {
|
||||
compare: callObjSimpleComparer("heading"),
|
||||
tableData: (callObj) => ({
|
||||
style: "color: yellow;",
|
||||
html: Math.round(callObj.heading)
|
||||
})
|
||||
},
|
||||
|
||||
CQz: {
|
||||
compare: false,
|
||||
tableData: (callObj) => ({
|
||||
name: "CQz",
|
||||
rawAttrs: callObj.style.cqz,
|
||||
html: callObj.cqza.join(",")
|
||||
})
|
||||
},
|
||||
|
||||
ITUz: {
|
||||
compare: false,
|
||||
tableData: (callObj) => ({
|
||||
name: "ITUz",
|
||||
rawAttrs: callObj.style.ituz,
|
||||
html: callObj.ituza.join(",")
|
||||
})
|
||||
},
|
||||
|
||||
PX: {
|
||||
compare: callObjSimpleComparer("px"),
|
||||
tableData: (callObj) => ({
|
||||
rawAttrs: callObj.style.px,
|
||||
html: callObj.px ? callObj.px : ""
|
||||
})
|
||||
},
|
||||
|
||||
LoTW: {
|
||||
compare: false,
|
||||
tableData: (callObj) =>
|
||||
{
|
||||
if (callObj.DEcall in window.opener.g_lotwCallsigns)
|
||||
{
|
||||
if (g_rosterSettings.maxLoTW < 27)
|
||||
{
|
||||
let months = (g_day - window.opener.g_lotwCallsigns[callObj.DEcall]) / 30;
|
||||
if (months > g_rosterSettings.maxLoTW)
|
||||
{
|
||||
return {
|
||||
style: "color: yellow;",
|
||||
align: "center",
|
||||
title: `Has not updated a QSO in ${Number(months).toYM()}`,
|
||||
html: "?"
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return {
|
||||
style: "color: #0F0;",
|
||||
align: "center",
|
||||
title: `Last Upload ${
|
||||
window.opener.userDayString(window.opener.g_lotwCallsigns[callObj.DEcall] * 86400000)
|
||||
}`,
|
||||
html: "✔"
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return {
|
||||
style: "color: #0F0;",
|
||||
align: "center",
|
||||
title: `Last Upload ${
|
||||
window.opener.userDayString(window.opener.g_lotwCallsigns[callObj.DEcall] * 86400000)
|
||||
}`,
|
||||
html: "✔"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
eQSL: {
|
||||
compare: false,
|
||||
tableData: (callObj) => ({
|
||||
style: "color: #0F0;",
|
||||
align: "center",
|
||||
html: (callObj.DEcall in window.opener.g_eqslCallsigns ? "✔" : "")
|
||||
})
|
||||
},
|
||||
|
||||
OQRS: {
|
||||
compare: false,
|
||||
tableData: (callObj) => ({
|
||||
style: "color: #0F0;",
|
||||
align: "center",
|
||||
html: (callObj.DEcall in window.opener.g_oqrsCallsigns ? "✔" : "")
|
||||
})
|
||||
},
|
||||
|
||||
Life: {
|
||||
compare: callObjSimpleComparer("life"),
|
||||
tableData: (callObj) => ({
|
||||
style: "color: #EEE;",
|
||||
class: "lifeCol",
|
||||
id: `lm${callObj.hash}`,
|
||||
html: (timeNowSec() - callObj.life).toDHMS15()
|
||||
})
|
||||
},
|
||||
|
||||
OAMS: {
|
||||
tableHeader: () => ({ description: "Off-Air Message User" }),
|
||||
compare: getterSimpleComparer((elem) => elem.callObj.gt != 0 ? 1 : 0),
|
||||
tableData: (callObj) =>
|
||||
{
|
||||
if (callObj.gt != 0)
|
||||
{
|
||||
if (callObj.reason.includes("oams"))
|
||||
{
|
||||
return {
|
||||
align: "center",
|
||||
style: "margin: 0; padding: 0; cursor: pointer; background-clip: content-box; box-shadow: 0 0 4px 4px inset #2222FFFF;",
|
||||
onClick: `openChatToCid("${callObj.gt}")`,
|
||||
html: "<img height='16px' style='' src='./img/gt_chat.png' />"
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return {
|
||||
align: "center",
|
||||
style: "margin: 0; padding: 0; cursor: pointer;",
|
||||
onClick: `openChatToCid("${callObj.gt}")`,
|
||||
html: "<img height='16px' style='' src='./img/gt_chat.png' />"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Age: {
|
||||
compare: callObjSimpleComparer("time"),
|
||||
tableData: (callObj) => ({
|
||||
style: "color: #EEE;",
|
||||
class: "timeCol",
|
||||
id: `tm${callObj.hash}`,
|
||||
title: (timeNowSec() - callObj.age).toDHMS(),
|
||||
html: (timeNowSec() - callObj.age).toDHMS15()
|
||||
})
|
||||
},
|
||||
|
||||
Spot: {
|
||||
compare: (a, b) =>
|
||||
{
|
||||
let cutoff = timeNowSec() - window.opener.g_receptionSettings.viewHistoryTimeSec;
|
||||
|
||||
if (a.callObj.spot.when <= cutoff) return -1;
|
||||
if (b.callObj.spot.when <= cutoff) return 1;
|
||||
|
||||
let aSNR = Number(a.callObj.spot.snr);
|
||||
let bSNR = Number(b.callObj.spot.snr);
|
||||
|
||||
if (aSNR > bSNR) return 1;
|
||||
if (aSNR < bSNR) return -1;
|
||||
|
||||
if (a.callObj.spot.when > b.callObj.spot.when) return 1;
|
||||
if (a.callObj.spot.when < b.callObj.spot.when) return -1;
|
||||
|
||||
return 0;
|
||||
},
|
||||
tableData: (callObj) => ({
|
||||
style: "color: #EEE;",
|
||||
class: "spotCol",
|
||||
id: `sp${callObj.hash}`,
|
||||
html: getSpotString(callObj)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,140 @@
|
|||
function sendAlerts(callRoster, rosterSettings)
|
||||
{
|
||||
var dirPath = window.opener.g_scriptDir;
|
||||
var scriptExists = false;
|
||||
var script = "cr-alert.sh";
|
||||
|
||||
var shouldAlert = 0;
|
||||
|
||||
for (entry in callRoster)
|
||||
{
|
||||
var callObj = callRoster[entry].callObj;
|
||||
|
||||
// chrbayer: what does the tx field mean? no alerts are generated (at all) if this is in place...
|
||||
// if (!callObj.tx) continue;
|
||||
|
||||
// TODO: Get rid of realtime
|
||||
if (g_rosterSettings.realtime == false)
|
||||
{
|
||||
var call = callObj.DEcall;
|
||||
g_scriptReport[call] = Object.assign({}, callObj);
|
||||
g_scriptReport[call].dxccName =
|
||||
window.opener.g_dxccToAltName[callObj.dxcc];
|
||||
g_scriptReport[call].distance = parseInt(
|
||||
callObj.distance *
|
||||
MyCircle.validateRadius(window.opener.distanceUnit.value)
|
||||
);
|
||||
|
||||
delete g_scriptReport[call].DEcall;
|
||||
g_scriptReport[call].rect = null;
|
||||
delete g_scriptReport[call].rect;
|
||||
delete g_scriptReport[call].style;
|
||||
delete g_scriptReport[call].wspr;
|
||||
delete g_scriptReport[call].qso;
|
||||
delete g_scriptReport[call].instance;
|
||||
|
||||
if (rosterSettings.callMode != "all")
|
||||
{
|
||||
g_scriptReport[call].shouldAlert = true;
|
||||
g_scriptReport[call].reason.push(g_rosterSettings.hunting);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
callObj.alerted == false &&
|
||||
rosterSettings.callMode == "all" &&
|
||||
callObj.shouldAlert == true
|
||||
)
|
||||
{
|
||||
callObj.alerted = true;
|
||||
shouldAlert++;
|
||||
}
|
||||
else if (callObj.alerted == false && rosterSettings.callMode != "all")
|
||||
{
|
||||
callObj.alerted = true;
|
||||
shouldAlert++;
|
||||
}
|
||||
|
||||
callObj.shouldAlert = false;
|
||||
}
|
||||
|
||||
// NOTE: Ring alerts if needed
|
||||
try
|
||||
{
|
||||
if (fs.existsSync(dirPath))
|
||||
{
|
||||
if (window.opener.g_platform == "windows")
|
||||
{
|
||||
script = "cr-alert.bat";
|
||||
}
|
||||
if (
|
||||
fs.existsSync(dirPath + script) &&
|
||||
g_rosterSettings.realtime == false
|
||||
)
|
||||
{
|
||||
scriptExists = true;
|
||||
scriptIcon.innerHTML =
|
||||
"<div class='buttonScript' onclick='window.opener.toggleCRScript();'>" +
|
||||
(window.opener.g_crScript == 1
|
||||
? "<font color='lightgreen'>Script Enabled</font>"
|
||||
: "<font color='yellow'>Script Disabled</font>") +
|
||||
"</div>";
|
||||
scriptIcon.style.display = "block";
|
||||
}
|
||||
else
|
||||
{
|
||||
scriptIcon.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {}
|
||||
|
||||
if (shouldAlert > 0)
|
||||
{
|
||||
if (window.opener.g_classicAlerts.huntRoster == true)
|
||||
{
|
||||
var notify = window.opener.huntRosterNotify.value;
|
||||
if (notify == "0")
|
||||
{
|
||||
var media = window.opener.huntRosterNotifyMedia.value;
|
||||
if (media != "none") window.opener.playAlertMediaFile(media);
|
||||
}
|
||||
else if (notify == "1")
|
||||
{
|
||||
window.opener.speakAlertString(
|
||||
window.opener.huntRosterNotifyWord.value
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
g_rosterSettings.realtime == false &&
|
||||
scriptExists &&
|
||||
window.opener.g_crScript == 1
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
fs.writeFileSync(
|
||||
dirPath + "cr-alert.json",
|
||||
JSON.stringify(g_scriptReport, null, 2)
|
||||
);
|
||||
|
||||
var thisProc = dirPath + script;
|
||||
var cp = require("child_process");
|
||||
var child = cp.spawn(thisProc, [], {
|
||||
detached: true,
|
||||
cwd: dirPath.slice(0, -1),
|
||||
stdio: ["ignore", "ignore", "ignore"]
|
||||
});
|
||||
child.unref();
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
conosle.log(e);
|
||||
}
|
||||
g_scriptReport = Object();
|
||||
}
|
||||
else g_scriptReport = Object();
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
// GridTracker Copyright © 2021 GridTracker.org
|
||||
// GridTracker Copyright © 2022 GridTracker.org
|
||||
// All rights reserved.
|
||||
// See LICENSE for more information.
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "GridTracker",
|
||||
"product_string_do_not_use": "gridtracker",
|
||||
"version": "1.21.0620",
|
||||
"version": "1.22.0503",
|
||||
"betaVersion": "",
|
||||
"description": "GridTracker, an amateur radio companion",
|
||||
"author": "Stephen Loomis (N0TTL) and GridTracker.org",
|
||||
|
@ -23,7 +23,7 @@
|
|||
"start": "run --mirror https://dl.nwjs.io/ ."
|
||||
},
|
||||
"build": {
|
||||
"nwVersion": "0.49.2",
|
||||
"nwVersion": "0.59.0",
|
||||
"output": "../dist/.",
|
||||
"targets": [
|
||||
"zip",
|
||||
|
@ -31,7 +31,7 @@
|
|||
],
|
||||
"mac": {
|
||||
"icon": "gridview.icns",
|
||||
"copyright": "Copyright (c) 2021 GridTracker.org",
|
||||
"copyright": "Copyright (c) 2022 GridTracker.org",
|
||||
"plistStrings": {
|
||||
"CFBundleIdentifier": "org.gridtracker.gridtracker",
|
||||
"CFBundleDocumentTypes": []
|
||||
|
@ -39,7 +39,7 @@
|
|||
},
|
||||
"win": {
|
||||
"icon": "gridview.ico",
|
||||
"copyright": "Copyright (c) 2021 GridTracker.org"
|
||||
"copyright": "Copyright (c) 2022 GridTracker.org"
|
||||
},
|
||||
"nsis": {
|
||||
"installDirectory": "$PROGRAMFILES\\${_APPNAME}",
|
||||
|
|
|
@ -65,7 +65,7 @@ VIAddVersionKey CompanyName "${COMPANY}"
|
|||
VIAddVersionKey CompanyWebsite "${URL}"
|
||||
VIAddVersionKey FileVersion "${VERSION}"
|
||||
VIAddVersionKey FileDescription "An Amateur Radio Community"
|
||||
VIAddVersionKey LegalCopyright "2021 Gridtracker.org"
|
||||
VIAddVersionKey LegalCopyright "2022 Gridtracker.org"
|
||||
InstallDirRegKey HKLM "${REGKEY}" Path
|
||||
ShowUninstDetails nevershow
|
||||
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
GridTracker Installation Script
|
||||
*/
|
||||
|
||||
# Installer Attributes
|
||||
RequestExecutionLevel highest
|
||||
SetCompressor /SOLID LZMA
|
||||
Unicode true
|
||||
!include Sections.nsh
|
||||
!include Registry.nsh
|
||||
!include LogicLib.nsh
|
||||
ReserveFile "${NSISDIR}/Plugins/x86-unicode/registry.dll"
|
||||
CRCCheck on
|
||||
|
||||
|
||||
# Define Common Variables
|
||||
!define NAME "GridTracker"
|
||||
!define COMPANY "Gridtracker.org"
|
||||
!define VERSION <versionplaceholder>
|
||||
!define URL "http://gridtracker.org"
|
||||
!define HELPURL "https://gitlab.com/gridtracker.org/gridtracker/-/wikis/Home"
|
||||
!define REGPATH_UNINSTSUBKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}"
|
||||
!define SMPATH "$SMPROGRAMS\${NAME}"
|
||||
!define /date CPYEAR "%Y"
|
||||
!define BUILDPATH "<buildplaceholder>"
|
||||
Name "${NAME} ${VERSION} Installer"
|
||||
Icon "${BUILDPATH}/dist/GridTracker-${VERSION}-win-x86/gridview.ico"
|
||||
OutFile "${BUILDPATH}/dist/GridTracker-Installer.${VERSION}.exe"
|
||||
|
||||
|
||||
VIProductVersion ${VERSION}.0
|
||||
VIAddVersionKey ProductName "${NAME}"
|
||||
VIAddVersionKey ProductVersion "${VERSION}"
|
||||
VIAddVersionKey CompanyName "${COMPANY}"
|
||||
VIAddVersionKey CompanyWebsite "${URL}"
|
||||
VIAddVersionKey FileVersion "${VERSION}"
|
||||
VIAddVersionKey FileDescription "An Amateur Radio Community"
|
||||
VIAddVersionKey LegalCopyright "${CPYEAR} Gridtracker.org"
|
||||
|
||||
|
||||
# Add registry reading plugin early on as we need to see if we are installed already
|
||||
|
||||
# Set Default install dir then look at uninstall key to find if previously installed #
|
||||
InstallDir "$ProgramFiles\${NAME}"
|
||||
|
||||
## For 32 bit installs on 64 bit OS this is located in the WOW6432Node [HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall] ##
|
||||
InstallDirRegKey HKLM "${REGPATH_UNINSTSUBKEY}" "InstallPath"
|
||||
|
||||
|
||||
# Pages displayed
|
||||
#Page license
|
||||
Page directory
|
||||
Page components
|
||||
Page instfiles
|
||||
|
||||
# Display license file to user #
|
||||
#LicenseData "LICENSE"
|
||||
|
||||
Function .onInit
|
||||
nsProcess::_FindProcess "GridTracker.exe"
|
||||
Pop $R0
|
||||
${If} $R0 = 0
|
||||
MessageBox MB_OK|MB_ICONEXCLAMATION "GridTracker is still running. Please close GridTracker and run the installer again."
|
||||
Abort
|
||||
${EndIf}
|
||||
call checkMSVC
|
||||
FunctionEnd
|
||||
|
||||
Function checkMSVC
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKCR "Installer\Dependencies\VC,redist.x86,x86,14.30,bundle" ""
|
||||
IfErrors 0 +15
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKCR "Installer\Dependencies\Microsoft.VS.VC_RuntimeMinimumVSU_x86,v14" ""
|
||||
IfErrors 0 +12
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKCR "Installer\Dependencies\Microsoft.VS.VC_RuntimeAdditionalVSU_x86,v14" ""
|
||||
IfErrors 0 +9
|
||||
ClearErrors
|
||||
ReadRegStr $0 HKCR "Installer\Products\679E80FBE29B63345BF612177149674C" "PackageCode"
|
||||
IfErrors 0 +6
|
||||
MessageBox MB_YESNO|MB_ICONQUESTION "GridTracker requires MSVC Runtime Libraries. Do you want to install them now?" IDYES InstallNow IDNO Next
|
||||
InstallNow:
|
||||
Call InstallMSVC
|
||||
Goto Next
|
||||
Next:
|
||||
|
||||
FunctionEnd
|
||||
|
||||
|
||||
Function InstallMSVC
|
||||
NSISdl::download "https://aka.ms/vs/17/release/vc_redist.x86.exe" "$TEMP\vc_redist.x86.exe" $0
|
||||
StrCmp $0 success fail
|
||||
success:
|
||||
ExecWait '"$TEMP\vc_redist.x86.exe" /PASSIVE /NORESTART' $1
|
||||
Goto is_reboot_requested
|
||||
fail:
|
||||
MessageBox MB_OK|MB_ICONEXCLAMATION "Unable to download MSVC Runtime files. Please see GridTracker.org for details on download"
|
||||
is_reboot_requested:
|
||||
${If} $1 = 1641
|
||||
${OrIf} $1 = 3010
|
||||
SetRebootFlag true
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
InstType "Full"
|
||||
InstType "Minimal"
|
||||
|
||||
Section "Program Files (Required)"
|
||||
SectionIn 1 2 RO
|
||||
SetOverwrite ifdiff
|
||||
|
||||
SetOutPath $InstDir
|
||||
File /r "${BUILDPATH}/dist/GridTracker-${VERSION}-win-x86/*"
|
||||
|
||||
CreateDirectory "${SMPATH}"
|
||||
CreateShortcut "${SMPATH}\${NAME}.lnk" "$InstDir\${NAME}.exe"
|
||||
CreateShortcut "${SMPATH}\Help Wiki.lnk" "${HELPURL}" "" "$InstDir\gridview.ico"
|
||||
CreateShortcut "${SMPATH}\Uninstall.lnk" $INSTDIR\uninstall.exe
|
||||
|
||||
WriteRegStr HKLM "${REGPATH_UNINSTSUBKEY}" "DisplayName" "${NAME}"
|
||||
WriteRegStr HKLM "${REGPATH_UNINSTSUBKEY}" "DisplayVersion" "${VERSION}"
|
||||
WriteRegStr HKLM "${REGPATH_UNINSTSUBKEY}" "Publisher" "${COMPANY}"
|
||||
WriteRegStr HKLM "${REGPATH_UNINSTSUBKEY}" "URLInfoAbout" "${URL}"
|
||||
WriteRegStr HKLM "${REGPATH_UNINSTSUBKEY}" "DisplayIcon" "$InstDir\gridview.ico"
|
||||
WriteRegStr HKLM "${REGPATH_UNINSTSUBKEY}" "UninstallString" '"$InstDir\uninstall.exe"'
|
||||
WriteRegStr HKLM "${REGPATH_UNINSTSUBKEY}" "QuietUninstallString" '"$InstDir\uninstall.exe" /S'
|
||||
WriteRegStr HKLM "${REGPATH_UNINSTSUBKEY}" "InstallPath" $InstDir
|
||||
WriteRegDWORD HKLM "${REGPATH_UNINSTSUBKEY}" "NoModify" 1
|
||||
WriteRegDWORD HKLM "${REGPATH_UNINSTSUBKEY}" "NoRepair" 1
|
||||
|
||||
WriteUninstaller "$InstDir\uninstall.exe"
|
||||
|
||||
SectionEnd
|
||||
|
||||
# Section for PDF when we have it #
|
||||
/*
|
||||
Section "Offline Help Docs"
|
||||
SectionIn 1
|
||||
SectionEnd
|
||||
*/
|
||||
|
||||
# Section for Locales when we have it #
|
||||
/*
|
||||
SectionGroup "Locales"
|
||||
SetOutPath $INSTDIR\locales
|
||||
Section "de"
|
||||
|
||||
SectionEnd
|
||||
|
||||
Section "es"
|
||||
|
||||
SectionEnd
|
||||
SectionGroupEnd
|
||||
*/
|
||||
|
||||
# Give User Option for Desktop Shortcut #
|
||||
Section "Desktop Shortcut"
|
||||
SectionIn 1
|
||||
CreateShortcut /NoWorkingDir "$DESKTOP\${NAME}.lnk" "$InstDir\${NAME}.exe"
|
||||
SectionEnd
|
||||
|
||||
# Uninstall stuffs #
|
||||
Section -un.Main
|
||||
RmDir /r /REBOOTOK $INSTDIR
|
||||
RmDir /r /REBOOTOK "${SMPATH}"
|
||||
Delete /REBOOTOK "$DESKTOP\${NAME}.lnk"
|
||||
DeleteRegKey HKLM "${REGPATH_UNINSTSUBKEY}"
|
||||
Delete "$InstDir\uninstall.exe"
|
||||
SectionEnd
|
Ładowanie…
Reference in New Issue