Refactor beacon runtime to design system modules

This commit is contained in:
thePR0M3TH3AN committed 2025-10-14 10:26:41 -04:00
1 parent 91d09ff320
commit 053623bdac
12 files changed
+1069 -888

No files matched your search

-41
View File
@@ -9,11 +9,6 @@
"version": "1.0.0",
"license": "GPL-3.0-or-later",
"dependencies": {
"angular": "^1.8.3",
"angular-route": "^1.8.3",
"angular-sanitize": "^1.8.3",
"moment": "^2.30.1",
"ng-file-upload": "^12.2.13",
"webtorrent": "^1.9.7"
},
"devDependencies": {
@@ -1028,27 +1023,6 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/angular": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/angular/-/angular-1.8.3.tgz",
"integrity": "sha512-5qjkWIQQVsHj4Sb5TcEs4WZWpFeVFHXwxEBHUhrny41D8UrBAd6T/6nPPAsLngJCReIOqi95W3mxdveveutpZw==",
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward.",
"license": "MIT"
},
"node_modules/angular-route": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/angular-route/-/angular-route-1.8.3.tgz",
"integrity": "sha512-kpIcRmDR2+o1FxDVVYy8Rvfab86/7LDbOgTRb9T+X9ewPQiBRuDEnZtM3oJYBiQLvAXDYTJXHV48n/bGE9Mv2g==",
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward.",
"license": "MIT"
},
"node_modules/angular-sanitize": {
"version": "1.8.3",
"resolved": "https://registry.npmjs.org/angular-sanitize/-/angular-sanitize-1.8.3.tgz",
"integrity": "sha512-2rxdqzlUVafUeWOwvY/FtyWk1pFTyCtzreeiTytG9m4smpuAEKaIJAjYeVwWsoV+nlTOcgpwV4W1OCmR+BQbUg==",
"deprecated": "For the actively supported Angular, see https://www.npmjs.com/package/@angular/core. AngularJS support has officially ended. For extended AngularJS support options, see https://goo.gle/angularjs-path-forward.",
"license": "MIT"
},
"node_modules/ansi-regex": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
@@ -3699,15 +3673,6 @@
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
"license": "MIT"
},
"node_modules/moment": {
"version": "2.30.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/mp4-box-encoding": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/mp4-box-encoding/-/mp4-box-encoding-1.4.1.tgz",
@@ -3788,12 +3753,6 @@
"integrity": "sha512-IXGPhl/yAiUU597gz+k5OYxYZkmLSWTcPPcpQjWABud9OK6m/ZNLrVdcEu4e7NgmOObFIhgZVg1jecPYT/6AoA==",
"license": "MIT"
},
"node_modules/ng-file-upload": {
"version": "12.2.13",
"resolved": "https://registry.npmjs.org/ng-file-upload/-/ng-file-upload-12.2.13.tgz",
"integrity": "sha512-YFjxwmVcNssYc8hq8eCbtYSliPnrObozSZRC9yg4GoDtI0xGKUeHgEcOh+nsMF/9cTzMB/lQZAYdf29oyQgF0g==",
"license": "MIT"
},
"node_modules/node-gyp-build": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
-5
View File
@@ -37,11 +37,6 @@
},
"license": "GPL-3.0-or-later",
"dependencies": {
"angular": "^1.8.3",
"angular-route": "^1.8.3",
"angular-sanitize": "^1.8.3",
"moment": "^2.30.1",
"ng-file-upload": "^12.2.13",
"webtorrent": "^1.9.7"
}
}
+6 -5
View File
@@ -10,19 +10,20 @@ const __dirname = path.dirname(__filename);
const repoRoot = path.resolve(__dirname, "..");
const entryPoint = path.join(repoRoot, "torrent/src/beacon-vendor.js");
const outDir = path.join(repoRoot, "torrent/dist");
const outFile = path.join(outDir, "beacon.js");
await mkdir(outDir, { recursive: true });
await build({
bundle: true,
entryPoints: { "beacon.vendor": entryPoint },
outdir: outDir,
format: "iife",
entryPoints: [entryPoint],
outfile: outFile,
format: "esm",
splitting: false,
platform: "browser",
target: ["es2019"],
target: ["es2020"],
minify: true,
sourcemap: false,
entryNames: "[name]",
loader: {
".css": "css",
".woff": "dataurl",
-4
View File
@@ -40,10 +40,6 @@ const IGNORED_FILES = new Set([
]);
const VIOLATION_ALLOWLIST = new Map([
[
"torrent/dist/beacon.vendor.js",
new Set(["Direct .style usage", "style.cssText usage"]),
],
["js/ui/utils/floatingPanelStyles.js", new Set(["Direct .style usage"])],
]);
+575 -332
View File
@@ -1,381 +1,624 @@
/* global WebTorrent, angular, moment */
import { registerBeaconToast } from "./ui/toastService.js";
import { registerTorrentTable } from "./ui/torrentTable.js";
import { createBeaconToast } from "./ui/toastService.js";
import { createTorrentTable } from "./ui/torrentTable.js";
const VERSION = "1.1";
const VERSION = "2.0";
// A smaller set of WebSocket trackers for reliability.
const trackers = [
const TRACKERS = [
"wss://tracker.btorrent.xyz",
"wss://tracker.openwebtorrent.com",
];
// Basic torrent options.
const torrentOpts = { announce: trackers };
const trackerOpts = { announce: trackers };
const TORRENT_OPTIONS = { announce: TRACKERS };
const TRACKER_OPTIONS = { announce: TRACKERS };
// Simple debug logger.
function dbg(msg) {
console.log("[DEBUG]", msg);
function formatBytes(num, speed = false) {
if (typeof num !== "number" || Number.isNaN(num)) {
return "";
}
if (num < 1) {
return speed ? "" : "0 B";
}
const units = ["B", "kB", "MB", "GB", "TB"];
const exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), units.length - 1);
const value = (num / Math.pow(1000, exponent)).toFixed(1);
return `${value} ${units[exponent]}${speed ? "/s" : ""}`;
}
// Create a WebTorrent client.
const client = new WebTorrent({ tracker: trackerOpts });
function formatProgress(value) {
if (typeof value !== "number" || Number.isNaN(value)) {
return "";
}
// Angular app definition.
const app = angular.module("BTorrent", ["ngRoute", "ngFileUpload"]);
return `${(value * 100).toFixed(1)}%`;
}
registerBeaconToast(app);
registerTorrentTable(app);
function formatRatio(value) {
if (typeof value !== "number" || !Number.isFinite(value)) {
return "0.00";
}
// Configure Angular routes.
app.config([
"$compileProvider",
"$locationProvider",
"$routeProvider",
function ($compileProvider, $locationProvider, $routeProvider) {
// Allow magnet, blob, etc. in Angular URLs.
$compileProvider.aHrefSanitizationWhitelist(
/^\s*(https?|magnet|blob|javascript):/
);
$locationProvider.html5Mode(false).hashPrefix("");
return value.toFixed(2);
}
// Define basic routes.
$routeProvider
.when("/view", {
templateUrl: "views/view.html",
controller: "ViewCtrl",
})
.when("/download", {
templateUrl: "views/download.html",
controller: "DownloadCtrl",
})
.otherwise({
templateUrl: "views/full.html",
controller: "FullCtrl",
});
},
]);
function torrentsMatch(a, b) {
if (!a || !b) {
return false;
}
// Warn user before they unload if torrents are still active.
app.run([
"$rootScope",
function ($rootScope) {
window.addEventListener("beforeunload", (e) => {
if ($rootScope.client && $rootScope.client.torrents.length > 0) {
e.preventDefault();
e.returnValue =
"Transfers are in progress. Are you sure you want to leave or refresh?";
return e.returnValue;
}
});
},
]);
if (a === b) {
return true;
}
// Main BTorrent controller.
app.controller("BTorrentCtrl", [
"$scope",
"$rootScope",
"$http",
"$log",
"beaconToast",
function ($scope, $rootScope, $http, $log, beaconToast) {
dbg("Starting app.js version " + VERSION);
if (a.infoHash && b.infoHash && a.infoHash === b.infoHash) {
return true;
}
if (!WebTorrent.WEBRTC_SUPPORT) {
beaconToast.error("Please use a browser with WebRTC support.", { sticky: true });
if (a.magnetURI && b.magnetURI && a.magnetURI === b.magnetURI) {
return true;
}
return false;
}
function prepareTorrentFiles(torrent) {
if (!torrent || !Array.isArray(torrent.files)) {
return;
}
torrent.files.forEach((file) => {
if (typeof file.priority !== "string") {
file.priority = "0";
}
$rootScope.client = client;
$rootScope.selectedTorrent = null;
$rootScope.processing = false;
// Global error handler.
client.on("error", (err) => {
dbg("Torrent client error: " + err);
beaconToast.error(err.message || err);
$rootScope.processing = false;
});
/**
* Called whenever a new torrent is added or we seed files.
*/
$rootScope.onTorrent = function (torrent, isSeed) {
dbg("Torrent added: " + torrent.magnetURI);
$rootScope.processing = false;
if (!isSeed) {
beaconToast.info(`Received ${torrent.name} metadata`);
}
if (!$rootScope.selectedTorrent) {
$rootScope.selectedTorrent = torrent;
}
// Generate file.blobURL for direct downloading in the file table.
torrent.files.forEach((file) => {
file.getBlobURL((err, url) => {
if (!err) {
file.url = url;
}
});
if (typeof file.getBlobURL === "function") {
file.getBlobURL((error, url) => {
if (error || !url) {
return;
}
file.url = url;
});
};
}
});
/**
* Add a magnet link or .torrent URL.
*/
$rootScope.addMagnet = function (magnet) {
if (!magnet) return;
$rootScope.processing = true;
dbg("Adding magnet: " + magnet);
client.add(magnet, torrentOpts, (torrent) => {
$rootScope.onTorrent(torrent, false);
$scope.$applyAsync();
if (torrent.torrentFile && typeof Blob === "function" && typeof URL !== "undefined") {
try {
const blob = new Blob([torrent.torrentFile], {
type: "application/x-bittorrent",
});
};
/**
* Seed local files.
*/
$rootScope.seedFiles = function (files) {
if (!files || !files.length) return;
$rootScope.processing = true;
dbg(`Seeding ${files.length} file(s)`);
client.seed(files, torrentOpts, (torrent) => {
$rootScope.onTorrent(torrent, true);
$scope.$applyAsync();
});
};
/**
* Remove/destroy a selected torrent.
*/
$rootScope.destroyedTorrent = function (err) {
if (err) {
console.error("Failed to destroy torrent:", err);
torrent.torrentFileBlobURL = URL.createObjectURL(blob);
if (!torrent.fileName) {
const name = torrent.name || "download";
torrent.fileName = `${name}.torrent`;
}
dbg("Destroyed torrent", $rootScope.selectedTorrent);
$rootScope.selectedTorrent = null;
$rootScope.processing = false;
};
} catch (error) {
console.warn("[beacon] Failed to create torrent blob URL", error);
}
}
}
/**
* Change the priority of an individual file (high, low, or don't download).
*/
$rootScope.changePriority = function (file) {
if (file.priority === "-1") {
file.deselect();
dbg("Deselected file", file);
function setFilePriority(file, value) {
if (!file) {
return;
}
const priorityValue = typeof value === "string" ? value : String(value ?? "0");
file.priority = priorityValue;
if (priorityValue === "-1") {
if (typeof file.deselect === "function") {
file.deselect();
}
return;
}
const numericPriority = Number.parseInt(priorityValue, 10);
if (!Number.isFinite(numericPriority)) {
return;
}
if (typeof file.select === "function") {
file.select(numericPriority);
}
}
function selectNextTorrent(current, torrents) {
if (!Array.isArray(torrents) || torrents.length === 0) {
return null;
}
if (!current) {
return torrents[0];
}
const existing = torrents.find((torrent) => torrentsMatch(torrent, current));
if (existing) {
return existing;
}
return torrents[0];
}
export function createBeaconApp({
documentRef = typeof document !== "undefined" ? document : null,
WebTorrentCtor,
} = {}) {
if (!documentRef) {
throw new Error("createBeaconApp requires a document reference");
}
const view = documentRef.defaultView || globalThis;
const WebTorrentClass =
typeof WebTorrentCtor === "function"
? WebTorrentCtor
: typeof view?.WebTorrent === "function"
? view.WebTorrent
: null;
if (!WebTorrentClass) {
throw new Error("createBeaconApp requires a WebTorrent constructor");
}
const toast = createBeaconToast(documentRef);
const client = new WebTorrentClass({ tracker: TRACKER_OPTIONS });
const elements = {
form: documentRef.querySelector('[data-beacon="magnet-form"]'),
magnetInput: documentRef.querySelector('[data-beacon="magnet-input"]'),
seedButton: documentRef.querySelector('[data-beacon="seed-button"]'),
seedInput: documentRef.querySelector('[data-beacon="seed-input"]'),
tableRoot: documentRef.querySelector('[data-beacon="torrent-table"]'),
selectedSection: documentRef.querySelector('[data-beacon="selected"]'),
selectedName: documentRef.querySelector('[data-beacon="selected-name"]'),
pauseButton: documentRef.querySelector('[data-beacon-action="pause"]'),
resumeButton: documentRef.querySelector('[data-beacon-action="resume"]'),
downloadAllButton: documentRef.querySelector('[data-beacon-action="download-all"]'),
removeButton: documentRef.querySelector('[data-beacon-action="remove"]'),
copyMagnetButton: documentRef.querySelector('[data-beacon-action="copy-magnet"]'),
infoHashValue: documentRef.querySelector('[data-beacon="info-hash"]'),
fileList: documentRef.querySelector('[data-beacon="file-list"]'),
stats: documentRef.querySelector('[data-beacon="client-stats"]'),
overlay: documentRef.querySelector('[data-beacon="processing-overlay"]'),
};
const table = elements.tableRoot
? createTorrentTable({
documentRef,
root: elements.tableRoot,
formatters: {
bytes: (value, speed = false) => formatBytes(value, speed),
progress: (value) => formatProgress(value),
ratio: (value) => formatRatio(value),
integer: (value) => (typeof value === "number" && Number.isFinite(value) ? Math.floor(value).toString() : "0"),
bytesPerSecond: (value) => formatBytes(value, true),
},
onSelect(torrent) {
state.selectedTorrent = torrent;
renderSelectedTorrent();
},
})
: null;
const state = {
selectedTorrent: null,
processing: false,
};
const cleanupTasks = [];
const intervalHandles = [];
function addCleanup(task) {
cleanupTasks.push(task);
}
function setProcessing(flag) {
state.processing = Boolean(flag);
if (elements.overlay) {
elements.overlay.hidden = !state.processing;
}
}
function getTorrents() {
return Array.isArray(client.torrents) ? [...client.torrents] : [];
}
function updateStats() {
if (!elements.stats) {
return;
}
const download = formatBytes(client.downloadSpeed, true) || "0 B/s";
const upload = formatBytes(client.uploadSpeed, true) || "0 B/s";
const ratio = formatRatio(client.ratio);
elements.stats.textContent = `Client stats: ↓ ${download} · ↑ ${upload} · Ratio: ${ratio}`;
}
function renderFileList(torrent) {
if (!elements.fileList) {
return;
}
elements.fileList.innerHTML = "";
if (!torrent || !Array.isArray(torrent.files) || !torrent.files.length) {
return;
}
torrent.files.forEach((file, index) => {
const row = documentRef.createElement("tr");
row.className = "align-top";
const nameCell = documentRef.createElement("td");
nameCell.className = "px-3 py-2";
if (file.done && file.url) {
const link = documentRef.createElement("a");
link.className = "text-info hover:text-info-strong";
link.href = file.url;
link.download = file.name || `file-${index + 1}`;
link.textContent = file.name || `File ${index + 1}`;
nameCell.appendChild(link);
} else {
file.select(file.priority);
dbg(`Selected with priority ${file.priority}`, file);
const span = documentRef.createElement("span");
span.textContent = file.name || `File ${index + 1}`;
nameCell.appendChild(span);
}
};
row.appendChild(nameCell);
/**
* Download all files in the selected torrent if it's 100% done.
* Creates a blob for each file, triggers a native download with <a>.
*/
$rootScope.downloadAll = function (torrent) {
if (!torrent) return;
if (torrent.progress < 1) {
alert("Torrent is not finished downloading yet.");
const sizeCell = documentRef.createElement("td");
sizeCell.className = "px-3 py-2 text-muted-strong";
sizeCell.textContent = formatBytes(file.length) || "0 B";
row.appendChild(sizeCell);
const priorityCell = documentRef.createElement("td");
priorityCell.className = "px-3 py-2";
const select = documentRef.createElement("select");
select.className = "select";
select.name = `${file.name || `file-${index + 1}`}-priority`;
select.setAttribute("aria-label", `Set priority for ${file.name || `file ${index + 1}`}`);
const options = [
{ value: "1", label: "High priority" },
{ value: "0", label: "Low priority" },
{ value: "-1", label: "Don't download" },
];
options.forEach((option) => {
const optionEl = documentRef.createElement("option");
optionEl.value = option.value;
optionEl.textContent = option.label;
if (option.value === file.priority) {
optionEl.selected = true;
}
select.appendChild(optionEl);
});
select.value = file.priority ?? "0";
select.addEventListener("change", (event) => {
setFilePriority(file, event.target.value);
});
priorityCell.appendChild(select);
row.appendChild(priorityCell);
elements.fileList.appendChild(row);
});
}
function renderSelectedTorrent() {
if (!elements.selectedSection) {
return;
}
const torrents = getTorrents();
state.selectedTorrent = selectNextTorrent(state.selectedTorrent, torrents);
const torrent = state.selectedTorrent;
elements.selectedSection.hidden = !torrent;
if (!torrent) {
return;
}
if (elements.selectedName) {
elements.selectedName.textContent = torrent.name || "Untitled torrent";
}
if (elements.pauseButton) {
elements.pauseButton.hidden = torrent.paused === true;
elements.pauseButton.disabled = torrent.paused === true;
}
if (elements.resumeButton) {
elements.resumeButton.hidden = torrent.paused !== true;
elements.resumeButton.disabled = torrent.paused !== true;
}
if (elements.downloadAllButton) {
elements.downloadAllButton.disabled = !(torrent.progress >= 1);
}
if (elements.infoHashValue) {
elements.infoHashValue.textContent = torrent.infoHash || "";
}
renderFileList(torrent);
}
function handleTorrentReady(torrent, { isSeed = false } = {}) {
setProcessing(false);
prepareTorrentFiles(torrent);
if (!isSeed) {
toast.info(`Received ${torrent.name || "torrent"} metadata`);
}
if (!state.selectedTorrent) {
state.selectedTorrent = torrent;
}
renderSelectedTorrent();
table?.render(getTorrents(), state.selectedTorrent);
}
function addMagnet(magnet) {
const trimmed = typeof magnet === "string" ? magnet.trim() : "";
if (!trimmed) {
return;
}
setProcessing(true);
client.add(trimmed, TORRENT_OPTIONS, (torrent) => {
handleTorrentReady(torrent, { isSeed: false });
});
}
function seedFiles(files) {
if (!Array.isArray(files) || files.length === 0) {
return;
}
setProcessing(true);
client.seed(files, TORRENT_OPTIONS, (torrent) => {
handleTorrentReady(torrent, { isSeed: true });
toast.success(`Seeding ${torrent.files.length} file(s)`);
});
}
function downloadAll(torrent) {
if (!torrent) {
return;
}
if (torrent.progress < 1) {
toast.warn("Torrent is not finished downloading yet.");
return;
}
torrent.files.forEach((file) => {
if (typeof file.getBlob !== "function") {
return;
}
torrent.files.forEach((file) => {
file.getBlob((err, blob) => {
if (err) {
console.error("Failed to get blob for file:", file.name, err);
return;
}
// Create an anchor to trigger the download.
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.classList.add("beacon-hidden-download");
a.setAttribute("data-beacon-hidden-download", "true");
a.href = blobUrl;
a.download = file.name;
// Append, click, remove, revoke.
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(blobUrl);
});
});
};
/**
* Copy the magnet URI of a torrent to the clipboard.
*/
$rootScope.copyMagnetURI = function (torrent) {
if (!torrent || !torrent.magnetURI) return;
const magnetURI = torrent.magnetURI;
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard
.writeText(magnetURI)
.then(() =>
beaconToast.success("Magnet URI copied to clipboard!")
)
.catch((err) => {
console.error("Clipboard error:", err);
beaconToast.error("Failed to copy magnet URI");
});
} else {
try {
const textarea = document.createElement("textarea");
textarea.value = magnetURI;
textarea.classList.add("beacon-clipboard-offscreen");
textarea.setAttribute("data-beacon-clipboard-state", "offscreen");
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
beaconToast.success("Magnet URI copied (fallback)!");
} catch (err) {
console.error("Clipboard fallback error:", err);
beaconToast.error("Failed to copy magnet URI");
file.getBlob((err, blob) => {
if (err || !blob) {
console.error("[beacon] Failed to get blob for file", file?.name, err);
toast.error("Failed to prepare file for download.");
return;
}
}
};
/**
* Save the .torrent file itself (via torrent.torrentFileBlobURL).
*/
$rootScope.saveTorrentFile = function (torrent) {
if (!torrent || !torrent.torrentFileBlobURL) return;
const fileName = torrent.fileName || `${torrent.name}.torrent`;
// Create a hidden <a> to force download of the .torrent file.
const a = document.createElement("a");
a.classList.add("beacon-hidden-download");
a.setAttribute("data-beacon-hidden-download", "true");
a.href = torrent.torrentFileBlobURL;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
},
]);
const blobUrl = URL.createObjectURL(blob);
const anchor = documentRef.createElement("a");
anchor.className = "beacon-hidden-download";
anchor.setAttribute("data-beacon-hidden-download", "true");
anchor.href = blobUrl;
anchor.download = file.name || "download";
documentRef.body.appendChild(anchor);
anchor.click();
documentRef.body.removeChild(anchor);
URL.revokeObjectURL(blobUrl);
});
});
}
// FullCtrl: handles the magnet input and torrent table for /full route.
app.controller("FullCtrl", [
"$scope",
"$rootScope",
"$location",
"$interval",
function ($scope, $rootScope, $location, $interval) {
// Handle magnet input
$scope.addMagnet = function () {
$rootScope.addMagnet($scope.torrentInput);
$scope.torrentInput = "";
};
// If we have a #magnet in the URL, add it automatically
if ($location.hash()) {
$rootScope.addMagnet($location.hash());
function copyMagnet(torrent) {
if (!torrent?.magnetURI) {
return;
}
const syncTorrents = () => {
const torrents = ($rootScope.client && $rootScope.client.torrents) || [];
$scope.torrentRows = torrents;
const magnet = torrent.magnetURI;
const clipboard = view?.navigator?.clipboard;
if ($rootScope.selectedTorrent) {
const stillPresent = torrents.some((torrent) => {
return (
torrent === $rootScope.selectedTorrent ||
(torrent?.magnetURI &&
torrent.magnetURI === $rootScope.selectedTorrent.magnetURI) ||
(torrent?.infoHash &&
torrent.infoHash === $rootScope.selectedTorrent.infoHash)
);
if (clipboard && typeof clipboard.writeText === "function") {
clipboard
.writeText(magnet)
.then(() => {
toast.success("Magnet URI copied to clipboard!");
})
.catch((error) => {
console.error("[beacon] Clipboard error", error);
toast.error("Failed to copy magnet URI");
});
return;
}
if (!stillPresent) {
$rootScope.selectedTorrent = torrents[0] || null;
}
} else if (torrents.length) {
$rootScope.selectedTorrent = torrents[0];
try {
const textarea = documentRef.createElement("textarea");
textarea.value = magnet;
textarea.className = "beacon-clipboard-offscreen";
textarea.setAttribute("data-beacon-clipboard-state", "offscreen");
documentRef.body.appendChild(textarea);
textarea.select();
documentRef.execCommand?.("copy");
documentRef.body.removeChild(textarea);
toast.success("Magnet URI copied (fallback)!");
} catch (error) {
console.error("[beacon] Clipboard fallback error", error);
toast.error("Failed to copy magnet URI");
}
}
function removeTorrent(torrent) {
if (!torrent) {
return;
}
torrent.destroy((error) => {
if (error) {
console.error("[beacon] Failed to destroy torrent", error);
toast.error("Failed to remove torrent");
}
const torrents = getTorrents();
state.selectedTorrent = selectNextTorrent(null, torrents);
table?.render(torrents, state.selectedTorrent);
renderSelectedTorrent();
});
}
function mount() {
console.log(`[beacon] Starting beacon runtime v${VERSION}`);
if (!toast) {
console.warn("[beacon] Toast service unavailable");
}
if (!WebTorrentClass.WEBRTC_SUPPORT) {
toast?.error("Please use a browser with WebRTC support.", { sticky: true });
}
if (elements.form) {
const submitHandler = (event) => {
event.preventDefault();
addMagnet(elements.magnetInput?.value || "");
if (elements.magnetInput) {
elements.magnetInput.value = "";
}
};
elements.form.addEventListener("submit", submitHandler);
addCleanup(() => elements.form.removeEventListener("submit", submitHandler));
}
if (elements.seedButton && elements.seedInput) {
const seedClickHandler = () => {
elements.seedInput.click();
};
const seedChangeHandler = () => {
const files = Array.from(elements.seedInput.files || []);
elements.seedInput.value = "";
seedFiles(files);
};
elements.seedButton.addEventListener("click", seedClickHandler);
elements.seedInput.addEventListener("change", seedChangeHandler);
addCleanup(() => {
elements.seedButton.removeEventListener("click", seedClickHandler);
elements.seedInput.removeEventListener("change", seedChangeHandler);
});
}
if (elements.pauseButton) {
const handler = () => {
if (state.selectedTorrent && typeof state.selectedTorrent.pause === "function") {
state.selectedTorrent.pause();
renderSelectedTorrent();
}
};
elements.pauseButton.addEventListener("click", handler);
addCleanup(() => elements.pauseButton.removeEventListener("click", handler));
}
if (elements.resumeButton) {
const handler = () => {
if (state.selectedTorrent && typeof state.selectedTorrent.resume === "function") {
state.selectedTorrent.resume();
renderSelectedTorrent();
}
};
elements.resumeButton.addEventListener("click", handler);
addCleanup(() => elements.resumeButton.removeEventListener("click", handler));
}
if (elements.downloadAllButton) {
const handler = () => downloadAll(state.selectedTorrent);
elements.downloadAllButton.addEventListener("click", handler);
addCleanup(() => elements.downloadAllButton.removeEventListener("click", handler));
}
if (elements.removeButton) {
const handler = () => removeTorrent(state.selectedTorrent);
elements.removeButton.addEventListener("click", handler);
addCleanup(() => elements.removeButton.removeEventListener("click", handler));
}
if (elements.copyMagnetButton) {
const handler = () => copyMagnet(state.selectedTorrent);
elements.copyMagnetButton.addEventListener("click", handler);
addCleanup(() => elements.copyMagnetButton.removeEventListener("click", handler));
}
const errorHandler = (error) => {
console.error("[beacon] Torrent client error", error);
toast?.error(error?.message || String(error));
setProcessing(false);
};
client.on("error", errorHandler);
addCleanup(() => client.removeListener("error", errorHandler));
$scope.selectTorrent = function (torrent) {
$rootScope.selectedTorrent = torrent;
const beforeUnloadHandler = (event) => {
if (client.torrents && client.torrents.length > 0) {
event.preventDefault();
event.returnValue =
"Transfers are in progress. Are you sure you want to leave or refresh?";
return event.returnValue;
}
return undefined;
};
if (view && typeof view.addEventListener === "function") {
view.addEventListener("beforeunload", beforeUnloadHandler);
addCleanup(() => view.removeEventListener("beforeunload", beforeUnloadHandler));
}
syncTorrents();
const poller = $interval(syncTorrents, 1000);
table?.render(getTorrents(), state.selectedTorrent);
renderSelectedTorrent();
updateStats();
setProcessing(false);
$scope.$on("$destroy", function () {
if (poller) {
$interval.cancel(poller);
const intervalId = view.setInterval(() => {
table?.render(getTorrents(), state.selectedTorrent);
renderSelectedTorrent();
updateStats();
}, 1000);
intervalHandles.push(intervalId);
const hash = view?.location?.hash;
if (typeof hash === "string" && hash.length > 1) {
addMagnet(hash.slice(1));
}
}
function destroy() {
intervalHandles.forEach((id) => view.clearInterval(id));
intervalHandles.length = 0;
cleanupTasks.forEach((task) => {
try {
task();
} catch (error) {
console.warn("[beacon] Cleanup task failed", error);
}
});
},
]);
cleanupTasks.length = 0;
// DownloadCtrl / ViewCtrl are minimal in this example.
app.controller("DownloadCtrl", [
"$scope",
"$rootScope",
"$location",
function ($scope, $rootScope, $location) {
$scope.addMagnet = function () {
$rootScope.addMagnet($scope.torrentInput);
$scope.torrentInput = "";
};
if ($location.hash()) {
$rootScope.addMagnet($location.hash());
table?.destroy();
try {
client.destroy();
} catch (error) {
console.warn("[beacon] Failed to destroy client", error);
}
},
]);
}
app.controller("ViewCtrl", [
"$scope",
"$rootScope",
"$location",
function ($scope, $rootScope, $location) {
$scope.addMagnet = function () {
$rootScope.addMagnet($scope.torrentInput);
$scope.torrentInput = "";
};
if ($location.hash()) {
$rootScope.addMagnet($location.hash());
}
},
]);
return { mount, destroy };
}
// Angular filters for size, progress, etc.
app.filter("pbytes", function () {
return function (num, speed) {
if (isNaN(num)) return "";
if (num < 1) return speed ? "" : "0 B";
const units = ["B", "kB", "MB", "GB", "TB"];
const exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), 4);
const val = (num / Math.pow(1000, exponent)).toFixed(1) * 1;
return `${val} ${units[exponent]}${speed ? "/s" : ""}`;
};
});
app.filter("progress", function () {
return function (val) {
if (typeof val !== "number") return "";
return (val * 100).toFixed(1) + "%";
};
});
app.filter("html", [
"$sce",
function ($sce) {
return function (input) {
return $sce.trustAsHtml(input);
};
},
]);
app.filter("humanTime", function () {
return function (millis) {
if (millis < 1000) return "";
const duration = moment.duration(millis).humanize();
return duration.charAt(0).toUpperCase() + duration.slice(1);
};
});
export default createBeaconApp;
+227 -16
View File
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html ng-app="BTorrent" lang="en">
<html lang="en">
<head>
<base href="./" />
<meta charset="UTF-8" />
@@ -13,20 +13,16 @@
content="bitvid, client, webtorrent, browser, torrent, stream, bittorrent, torrenting, sharing, filesharing"
/>
<!-- Favicon -->
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<!-- Scripts: webtorrent, angular, etc. -->
<script src="../js/tracking.js" defer></script>
<script defer src="dist/beacon.vendor.js"></script>
<!--<script src="https://cdn.jsdelivr.net/combine/npm/webtorrent/webtorrent.min.js,npm/moment@2,npm/[email protected]/angular.min.js,npm/angular-[email protected]/angular-route.min.js,npm/angular-[email protected]/angular-sanitize.min.js,npm/angular-ui-grid@3/ui-grid.min.js,gh/matowens/ng-notify/dist/ng-notify.min.js,npm/ng-file-[email protected]/dist/ng-file-upload.min.js"></script>-->
<script src="../js/webtorrent.min.js" defer></script>
<script type="module" src="dist/beacon.js"></script>
<!-- Local styles -->
<link rel="stylesheet" href="../css/tailwind.generated.css" />
</head>
<body class="bg-surface font-sans text-text" ng-controller="BTorrentCtrl" ng-cloak="">
<!-- Header with container -->
<body class="bg-surface font-sans text-text">
<header class="ds-header border-b border-border-translucent-medium bg-surface">
<div class="mx-auto flex max-w-5xl items-center px-4 py-6 sm:px-6 lg:px-8">
<a
@@ -72,14 +68,232 @@
</div>
</header>
<!-- Main content -->
<div id="viewer"></div>
<div id="view" ng-view></div>
<main class="mx-auto max-w-5xl px-4 py-6 sm:px-6 lg:px-8 bv-stack">
<section class="card p-6">
<form
class="bv-stack bv-stack--tight md:flex md:flex-row md:items-end md:gap-md"
data-beacon="magnet-form"
>
<div class="bv-stack bv-stack--tight flex-1">
<label
class="text-xs font-semibold uppercase tracking-wide text-muted-strong"
for="torrentInput"
>
Magnet, hash, or HTTPS .torrent URL
</label>
<input
id="torrentInput"
class="input"
type="text"
placeholder="magnet:?xt=…"
data-beacon="magnet-input"
autocomplete="off"
/>
</div>
<div class="flex flex-wrap items-center gap-3 md:justify-end">
<button type="submit" class="btn inline-flex items-center gap-2">
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M12 3v14"></path>
<path d="m6 11 6 6 6-6"></path>
<path d="M19 21H5"></path>
</svg>
Download
</button>
<input
type="file"
multiple
class="hidden"
data-beacon="seed-input"
aria-hidden="true"
/>
<button
type="button"
class="btn-ghost inline-flex items-center gap-2"
data-beacon="seed-button"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M12 21V7"></path>
<path d="m6 13 6-6 6 6"></path>
<path d="M5 21h14"></path>
</svg>
Seed files
</button>
</div>
</form>
</section>
<section class="card overflow-hidden" aria-label="Active torrents">
<div data-beacon="torrent-table"></div>
</section>
<section class="card p-6" data-beacon="selected" hidden>
<div class="grid gap-xl lg:grid-cols-2">
<div class="bv-stack bv-stack--tight overflow-auto">
<div class="bv-stack bv-stack--tight">
<h2 class="text-lg font-semibold text-text" data-beacon="selected-name"></h2>
<div class="flex flex-wrap gap-2">
<button
type="button"
class="btn-ghost inline-flex items-center gap-2"
data-beacon-action="pause"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<rect x="6" y="4" width="4" height="16"></rect>
<rect x="14" y="4" width="4" height="16"></rect>
</svg>
Pause
</button>
<button
type="button"
class="btn-ghost inline-flex items-center gap-2"
data-beacon-action="resume"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<polygon points="6 4 20 12 6 20 6 4"></polygon>
</svg>
Resume
</button>
<button
type="button"
class="btn inline-flex items-center gap-2"
data-beacon-action="download-all"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M12 3v14"></path>
<path d="m6 11 6 6 6-6"></path>
</svg>
Download all
</button>
<button
type="button"
class="btn-ghost inline-flex items-center gap-2"
data-variant="critical"
data-beacon-action="remove"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M18 6L6 18"></path>
<path d="M6 6l12 12"></path>
</svg>
Remove
</button>
</div>
</div>
<div class="bv-stack bv-stack--tight">
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted">
Share
</h3>
<ul class="bv-stack bv-stack--tight text-sm text-muted-strong">
<li>
<button
type="button"
class="btn-ghost inline-flex items-center gap-2 text-xs"
data-beacon-action="copy-magnet"
>
Copy magnet
</button>
</li>
<li>
<strong class="font-semibold text-text">Hash:</strong>
<span data-beacon="info-hash"></span>
</li>
</ul>
</div>
</div>
<div class="bv-stack bv-stack--tight">
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted">
Files
</h3>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-border-translucent text-sm">
<thead class="bg-surface-alt text-muted-strong">
<tr>
<th class="px-3 py-2 text-left font-medium">Name</th>
<th class="px-3 py-2 text-left font-medium">Size</th>
<th class="px-3 py-2 text-left font-medium">Priority</th>
</tr>
</thead>
<tbody
class="divide-y divide-border-translucent bg-surface"
data-beacon="file-list"
></tbody>
</table>
</div>
</div>
</div>
</section>
<div class="text-center text-sm font-semibold text-muted" data-beacon="client-stats">
Client stats: ↓ 0 B/s · ↑ 0 B/s · Ratio: 0.00
</div>
</main>
<!-- Processing Spinner -->
<div
class="fixed inset-0 z-[60] flex items-center justify-center bg-overlay-muted/70 backdrop-blur-md"
ng-show="client.processing"
data-beacon="processing-overlay"
hidden
>
<svg
class="h-12 w-12 animate-spin text-info-strong"
@@ -104,8 +318,5 @@
></path>
</svg>
</div>
<!-- Local Angular code -->
<script type="module" src="app.js"></script>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
var O={info:"torrent-toast torrent-toast--info",success:"torrent-toast torrent-toast--success",error:"torrent-toast torrent-toast--error",warn:"torrent-toast torrent-toast--warn"},V="transition duration-200 ease-out",Y="beacon-toast-motion",q="data-beacon-motion";function J(e,t){let a=e?.defaultView;if(a&&typeof a.requestAnimationFrame=="function"){a.requestAnimationFrame(t);return}setTimeout(t,16)}function Q(e){let t=e||(typeof document<"u"?document:null);if(!t)return null;let a=t.getElementById("beacon-toast-container");if(!a){a=t.createElement("div"),a.id="beacon-toast-container",a.setAttribute("role","region"),a.setAttribute("aria-live","polite"),a.className=["pointer-events-none","fixed","inset-x-0","top-4","z-[70]","flex","flex-col","items-center","gap-3","px-4"].join(" ");let i=t.body||t.getElementsByTagName?.("body")?.[0];i&&i.appendChild(a)}return a}function X(e,t,a){let i=e.createElement("div");i.className=[V,a].join(" "),i.setAttribute("role","status"),i.setAttribute("tabindex","0"),i.textContent=t;let o=e.createElement("button");o.type="button",o.className=["absolute","right-3","top-3","rounded","p-1","text-current/70","hover:text-current","focus-visible:outline","focus-visible:outline-2","focus-visible:outline-offset-2","focus-visible:outline-info"].join(" "),o.setAttribute("aria-label","Dismiss notification"),o.innerHTML='<svg class="h-4 w-4" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.75 3.75l8.5 8.5"></path><path d="M12.25 3.75l-8.5 8.5"></path></svg>';let d=e.createElement("div");return d.className=["relative","w-full",V,Y].join(" "),d.setAttribute(q,"exit"),d.appendChild(i),i.appendChild(o),{wrapper:d,toast:i,closeButton:o}}function Z(e,t=setTimeout,a=clearTimeout){return{show(i,o={}){if(!i)return;let d=o.type&&O[o.type]?o.type:"info",n=Q(e);if(!n)return;let{wrapper:m,toast:c,closeButton:T}=X(e,i,O[d]);n.appendChild(m),J(e,()=>{m.setAttribute(q,"enter")});let w=typeof o.duration=="number"?o.duration:3500,p=()=>{m.setAttribute(q,"exit");let S=t(()=>{m.parentNode&&m.parentNode.removeChild(m)},200);return T.removeEventListener("click",E),c.removeEventListener("keydown",h),T.removeEventListener("keydown",h),S},E=()=>p(),h=S=>{S.key==="Escape"&&(S.stopPropagation(),p())};T.addEventListener("click",E),c.addEventListener("keydown",h),T.addEventListener("keydown",h);let N=null;return o.sticky||(N=t(()=>{p()},w)),{dismiss(){N&&a(N),p()}}},set(i,o){return typeof o=="string"?this.show(i,{type:o}):this.show(i,o)},info(i,o={}){return this.show(i,{...o,type:"info"})},success(i,o={}){return this.show(i,{...o,type:"success"})},error(i,o={}){return this.show(i,{...o,type:"error"})},warn(i,o={}){return this.show(i,{...o,type:"warn"})}}}function R(e,t=setTimeout,a=clearTimeout){return Z(e,t,a)}var $=[{key:"name",label:"Name",headerClass:"w-full sm:w-1/3 text-left",cellClass:"font-medium text-text truncate"},{key:"progress",label:"Progress",headerClass:"w-24 text-right",cellClass:"tabular-nums text-right",formatter:"progress"},{key:"downloadSpeed",label:"\u2193 Speed",headerClass:"w-24 text-right",cellClass:"tabular-nums text-right",formatter:"bytesPerSecond"},{key:"uploadSpeed",label:"\u2191 Speed",headerClass:"w-24 text-right",cellClass:"tabular-nums text-right",formatter:"bytesPerSecond"},{key:"numPeers",label:"Peers",headerClass:"w-20 text-right",cellClass:"tabular-nums text-right",formatter:"integer"},{key:"ratio",label:"Ratio",headerClass:"w-20 text-right",cellClass:"tabular-nums text-right",formatter:"ratio"}];function ee(e){return e?e.infoHash||e.magnetURI||e.name||String(Math.random()):""}function te(e,t){return!e||!t?!1:e===t||e.magnetURI&&e.magnetURI===t.magnetURI||e.infoHash&&e.infoHash===t.infoHash}function ne(e){return typeof e!="number"||Number.isNaN(e)?"":`${(e*100).toFixed(1)}%`}function re(e){return typeof e!="number"||!Number.isFinite(e)?"0.00":e.toFixed(2)}function oe(e){return typeof e!="number"||!Number.isFinite(e)?"0":Math.max(0,Math.floor(e)).toString()}function ae(e,t){if(typeof t=="function")return t(e,!0)||"";if(typeof e!="number"||Number.isNaN(e)||e<1)return"";let a=["B","kB","MB","GB","TB"],i=Math.min(Math.floor(Math.log(e)/Math.log(1e3)),a.length-1);return`${(e/Math.pow(1e3,i)).toFixed(1)} ${a[i]}/s`}function se(e,t){let a=e.formatter;if(typeof a=="function")return a;let i=t?.[a];if(typeof i=="function")return i;switch(a){case"progress":return ne;case"ratio":return re;case"integer":return oe;case"bytesPerSecond":return o=>ae(o,t?.bytes);default:return o=>o}}function W({documentRef:e=typeof document<"u"?document:null,root:t,onSelect:a,formatters:i={}}={}){if(!e)throw new Error("createTorrentTable requires a document reference");if(!(t instanceof e.defaultView.HTMLElement))throw new Error("createTorrentTable requires a valid root element");let o=e;t.innerHTML="";let d=o.createElement("div");d.className="overflow-hidden rounded-xl border border-border-translucent bg-surface shadLine truncated
-84
View File
@@ -1,84 +0,0 @@
(()=>{var gu=Object.create;var zf=Object.defineProperty;var vu=Object.getOwnPropertyDescriptor;var bu=Object.getOwnPropertyNames;var yu=Object.getPrototypeOf,_u=Object.prototype.hasOwnProperty;var Ni=(yt=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(yt,{get:(Ke,ct)=>(typeof require!="undefined"?require:Ke)[ct]}):yt)(function(yt){if(typeof require!="undefined")return require.apply(this,arguments);throw Error('Dynamic require of "'+yt+'" is not supported')});var _i=(yt,Ke)=>()=>(Ke||yt((Ke={exports:{}}).exports,Ke),Ke.exports);var wu=(yt,Ke,ct,ut)=>{if(Ke&&typeof Ke=="object"||typeof Ke=="function")for(let rt of bu(Ke))!_u.call(yt,rt)&&rt!==ct&&zf(yt,rt,{get:()=>Ke[rt],enumerable:!(ut=vu(Ke,rt))||ut.enumerable});return yt};var eo=(yt,Ke,ct)=>(ct=yt!=null?gu(yu(yt)):{},wu(Ke||!yt||!yt.__esModule?zf(ct,"default",{value:yt,enumerable:!0}):ct,yt));var Wf=_i(()=>{(function(yt){"use strict";var Ke={objectMaxDepth:5,urlErrorParamsEnabled:!0};function ct(t){if(U(t))x(t.objectMaxDepth)&&(Ke.objectMaxDepth=ut(t.objectMaxDepth)?t.objectMaxDepth:NaN),x(t.urlErrorParamsEnabled)&&Y(t.urlErrorParamsEnabled)&&(Ke.urlErrorParamsEnabled=t.urlErrorParamsEnabled);else return Ke}function ut(t){return ee(t)&&t>0}function rt(t,d){d=d||Error;var w="https://errors.angularjs.org/1.8.3/",A=w.replace(".","\\.")+"[\\s\\S]*",L=new RegExp(A,"g");return function(){var Z=arguments[0],W=arguments[1],z="["+(t?t+":":"")+Z+"] ",H=J(arguments,2).map(function(ce){return Ue(ce,Ke.objectMaxDepth)}),ne,ie;if(z+=W.replace(/\{\d+\}/g,function(ce){var de=+ce.slice(1,-1);return de<H.length?H[de].replace(L,""):ce}),z+=`
`+w+(t?t+"/":"")+Z,Ke.urlErrorParamsEnabled)for(ie=0,ne="?";ie<H.length;ie++,ne="&")z+=ne+"p"+ie+"="+encodeURIComponent(H[ie]);return new d(z)}}var qe=/^\/(.+)\/([a-z]*)$/,Te="validity",fe=Object.prototype.hasOwnProperty,Ce=function(t){return X(t)?t.toLowerCase():t},$=function(t){return X(t)?t.toUpperCase():t},Ye,Re,Xe,xe=[].slice,je=[].splice,_t=[].push,_=Object.prototype.toString,K=Object.getPrototypeOf,R=rt("ng"),l=yt.angular||(yt.angular={}),y,m=0;Ye=yt.document.documentMode;function p(t){if(t==null||b(t))return!1;if(G(t)||X(t)||Re&&t instanceof Re)return!0;var d="length"in Object(t)&&t.length;return ee(d)&&(d>=0&&d-1 in t||typeof t.item=="function")}function n(t,d,w){var A,L;if(t)if(B(t))for(A in t)A!=="prototype"&&A!=="length"&&A!=="name"&&t.hasOwnProperty(A)&&d.call(w,t[A],A,t);else if(G(t)||p(t)){var Z=typeof t!="object";for(A=0,L=t.length;A<L;A++)(Z||A in t)&&d.call(w,t[A],A,t)}else if(t.forEach&&t.forEach!==n)t.forEach(d,w,t);else if(j(t))for(A in t)d.call(w,t[A],A,t);else if(typeof t.hasOwnProperty=="function")for(A in t)t.hasOwnProperty(A)&&d.call(w,t[A],A,t);else for(A in t)fe.call(t,A)&&d.call(w,t[A],A,t);return t}function u(t,d,w){for(var A=Object.keys(t).sort(),L=0;L<A.length;L++)d.call(w,t[A[L]],A[L]);return A}function o(t){return function(d,w){t(w,d)}}function a(){return++m}function f(t,d){d?t.$$hashKey=d:delete t.$$hashKey}function s(t,d,w){for(var A=t.$$hashKey,L=0,Z=d.length;L<Z;++L){var W=d[L];if(!(!U(W)&&!B(W)))for(var z=Object.keys(W),H=0,ne=z.length;H<ne;H++){var ie=z[H],ce=W[ie];w&&U(ce)?ue(ce)?t[ie]=new Date(ce.valueOf()):I(ce)?t[ie]=new RegExp(ce):ce.nodeName?t[ie]=ce.cloneNode(!0):Ze(ce)?t[ie]=ce.clone():ie!=="__proto__"&&(U(t[ie])||(t[ie]=G(ce)?[]:{}),s(t[ie],[ce],!0)):t[ie]=ce}}return f(t,A),t}function e(t){return s(t,xe.call(arguments,1),!1)}function r(t){return s(t,xe.call(arguments,1),!0)}function i(t){return parseInt(t,10)}var c=Number.isNaN||function(d){return d!==d};function h(t,d){return e(Object.create(t),d)}function g(){}g.$inject=[];function S(t){return t}S.$inject=[];function k(t){return function(){return t}}function M(t){return B(t.toString)&&t.toString!==_}function E(t){return typeof t=="undefined"}function x(t){return typeof t!="undefined"}function U(t){return t!==null&&typeof t=="object"}function j(t){return t!==null&&typeof t=="object"&&!K(t)}function X(t){return typeof t=="string"}function ee(t){return typeof t=="number"}function ue(t){return _.call(t)==="[object Date]"}function G(t){return Array.isArray(t)||t instanceof Array}function T(t){var d=_.call(t);switch(d){case"[object Error]":return!0;case"[object Exception]":return!0;case"[object DOMException]":return!0;default:return t instanceof Error}}function B(t){return typeof t=="function"}function I(t){return _.call(t)==="[object RegExp]"}function b(t){return t&&t.window===t}function C(t){return t&&t.$evalAsync&&t.$watch}function N(t){return _.call(t)==="[object File]"}function V(t){return _.call(t)==="[object FormData]"}function D(t){return _.call(t)==="[object Blob]"}function Y(t){return typeof t=="boolean"}function te(t){return t&&B(t.then)}var pe=/^\[object (?:Uint8|Uint8Clamped|Uint16|Uint32|Int8|Int16|Int32|Float32|Float64)Array]$/;function le(t){return t&&ee(t.length)&&pe.test(_.call(t))}function be(t){return _.call(t)==="[object ArrayBuffer]"}var we=function(t){return X(t)?t.trim():t},Be=function(t){return t.replace(/([-()[\]{}+?*.$^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")};function Ze(t){return!!(t&&(t.nodeName||t.prop&&t.attr&&t.find))}function gt(t){var d={},w=t.split(","),A;for(A=0;A<w.length;A++)d[w[A]]=!0;return d}function st(t){return Ce(t.nodeName||t[0]&&t[0].nodeName)}function _e(t,d){return Array.prototype.indexOf.call(t,d)!==-1}function Le(t,d){var w=t.indexOf(d);return w>=0&&t.splice(w,1),w}function ze(t,d,w){var A=[],L=[];if(w=ut(w)?w:NaN,d){if(le(d)||be(d))throw R("cpta","Can't copy! TypedArray destination cannot be mutated.");if(t===d)throw R("cpi","Can't copy! Source and destination are identical.");return G(d)?d.length=0:n(d,function(H,ne){ne!=="$$hashKey"&&delete d[ne]}),A.push(t),L.push(d),Z(t,d,w)}return W(t,w);function Z(H,ne,ie){if(ie--,ie<0)return"...";var ce=ne.$$hashKey,de;if(G(H))for(var Ee=0,Se=H.length;Ee<Se;Ee++)ne.push(W(H[Ee],ie));else if(j(H))for(de in H)ne[de]=W(H[de],ie);else if(H&&typeof H.hasOwnProperty=="function")for(de in H)H.hasOwnProperty(de)&&(ne[de]=W(H[de],ie));else for(de in H)fe.call(H,de)&&(ne[de]=W(H[de],ie));return f(ne,ce),ne}function W(H,ne){if(!U(H))return H;var ie=A.indexOf(H);if(ie!==-1)return L[ie];if(b(H)||C(H))throw R("cpws","Can't copy! Making copies of Window or Scope instances is not supported.");var ce=!1,de=z(H);return de===void 0&&(de=G(H)?[]:Object.create(K(H)),ce=!0),A.push(H),L.push(de),ce?Z(H,de,ne):de}function z(H){switch(_.call(H)){case"[object Int8Array]":case"[object Int16Array]":case"[object Int32Array]":case"[object Float32Array]":case"[object Float64Array]":case"[object Uint8Array]":case"[object Uint8ClampedArray]":case"[ Line truncated
`+Ge.stack),Nr("modulerr",`Failed to instantiate module {0} due to:
{1}`,$e,Ge.stack||Ge.message||Ge)}}),ye}function Oe(He,ye){function ge(Je,lt){if(He.hasOwnProperty(Je)){if(He[Je]===w)throw Nr("cdep","Circular dependency found: {0}",Je+" <- "+L.join(" <- "));return He[Je]}else try{return L.unshift(Je),He[Je]=w,He[Je]=ye(Je,lt),He[Je]}catch(xt){throw He[Je]===w&&delete He[Je],xt}finally{L.shift()}}function $e(Je,lt,xt){for(var Tt=[],wt=di.$$annotate(Je,d,xt),It=0,Jt=wt.length;It<Jt;It++){var Yt=wt[It];if(typeof Yt!="string")throw Nr("itkn","Incorrect injection token! Expected service name as string, got {0}",Yt);Tt.push(lt&&lt.hasOwnProperty(Yt)?lt[Yt]:ge(Yt,xt))}return Tt}function ke(Je){if(Ye||typeof Je!="function")return!1;var lt=Je.$$ngIsClass;return Y(lt)||(lt=Je.$$ngIsClass=/^class\b/.test(Xi(Je))),lt}function Ge(Je,lt,xt,Tt){typeof xt=="string"&&(Tt=xt,xt=null);var wt=$e(Je,xt,Tt);return G(Je)&&(Je=Je[Je.length-1]),ke(Je)?(wt.unshift(null),new(Function.prototype.bind.apply(Je,wt))):Je.apply(lt,wt)}function at(Je,lt,xt){var Tt=G(Je)?Je[Je.length-1]:Je,wt=$e(Je,lt,xt);return wt.unshift(null),new(Function.prototype.bind.apply(Tt,wt))}return{invoke:Ge,instantiate:at,get:ge,annotate:di.$$annotate,has:function(Je){return W.hasOwnProperty(Je+A)||He.hasOwnProperty(Je)}}}}di.$$annotate=ya;function _a(){var t=!0;this.disableAutoScrolling=function(){t=!1},this.$get=["$window","$location","$rootScope",function(d,w,A){var L=d.document;function Z(ne){var ie=null;return Array.prototype.some.call(ne,function(ce){if(st(ce)==="a")return ie=ce,!0}),ie}function W(){var ne=H.yOffset;if(B(ne))ne=ne();else if(Ze(ne)){var ie=ne[0],ce=d.getComputedStyle(ie);ce.position!=="fixed"?ne=0:ne=ie.getBoundingClientRect().bottom}else ee(ne)||(ne=0);return ne}function z(ne){if(ne){ne.scrollIntoView();var ie=W();if(ie){var ce=ne.getBoundingClientRect().top;d.scrollBy(0,ce-ie)}}else d.scrollTo(0,0)}function H(ne){ne=X(ne)?ne:ee(ne)?ne.toString():w.hash();var ie;ne?(ie=L.getElementById(ne))||(ie=Z(L.getElementsByName(ne)))?z(ie):ne==="top"&&z(null):z(null)}return t&&A.$watch(function(){return w.hash()},function(ie,ce){ie===ce&&ie===""||ha(function(){A.$evalAsync(H)})}),H}]}var co=rt("$animate"),wa=1,fo="ng-animate";function $i(t,d){return!t&&!d?"":t?d?(G(t)&&(t=t.join(" ")),G(d)&&(d=d.join(" ")),t+" "+d):t:d}function ho(t){for(var d=0;d<t.length;d++){var w=t[d];if(w.nodeType===wa)return w}}function Ea(t){X(t)&&(t=t.split(" "));var d=Ft();return n(t,function(w){w.length&&(d[w]=!0)}),d}function Or(t){return U(t)?t:{}}var Sa=function(){this.$get=g},As=function(){var t=new Ki,d=[];this.$get=["$$AnimateRunner","$rootScope",function(w,A){return{enabled:g,on:g,off:g,pin:g,push:function(z,H,ne,ie){ie&&ie(),ne=ne||{},ne.from&&z.css(ne.from),ne.to&&z.css(ne.to),(ne.addClass||ne.removeClass)&&W(z,ne.addClass,ne.removeClass);var ce=new w;return ce.complete(),ce}};function L(z,H,ne){var ie=!1;return H&&(H=X(H)?H.split(" "):G(H)?H:[],n(H,function(ce){ce&&(ie=!0,z[ce]=ne)})),ie}function Z(){n(d,function(z){var H=t.get(z);if(H){var ne=Ea(z.attr("class")),ie="",ce="";n(H,function(de,Ee){var Se=!!ne[Ee];de!==Se&&(de?ie+=(ie.length?" ":"")+Ee:ce+=(ce.length?" ":"")+Ee)}),n(z,function(de){ie&&Wi(de,ie),ce&&zi(de,ce)}),t.delete(z)}}),d.length=0}function W(z,H,ne){var ie=t.get(z)||{},ce=L(ie,H,!0),de=L(ie,ne,!1);(ce||de)&&(t.set(z,ie),d.push(z),d.length===1&&A.$$postDigest(Z))}}]},xa=["$provide",function(t){var d=this,w=null,A=null;this.$$registeredAnimations=Object.create(null),this.register=function(L,Z){if(L&&L.charAt(0)!==".")throw co("notcsel","Expecting class selector starting with '.' got '{0}'.",L);var W=L+"-animation";d.$$registeredAnimations[L.substr(1)]=W,t.factory(W,Z)},this.customFilter=function(L){return arguments.length===1&&(A=B(L)?L:null),A},this.classNameFilter=function(L){if(arguments.length===1&&(w=L instanceof RegExp?L:null,w)){var Z=new RegExp("[(\\s|\\/)]"+fo+"[(\\s|\\/)]");if(Z.test(w.toString()))throw w=null,co("nongcls",'$animateProvider.classNameFilter(regex) prohibits accepting a regex value which matches/contains the "{0}" CSS class.',fo)}return w},this.$get=["$$animateQueue",function(L){function Z(W,z,H){if(H){var ne=ho(H);ne&&!ne.parentNode&&!ne.previousElementSibling&&(H=null)}H?H.after(W):z.prepend(W)}return{on:L.on,off:L.off,pin:L.pin,enabled:L.enabled,cancel:function(W){W.cancel&&W.cancel()},enter:function(W,z,H,ne){return z=z&&Re(z),H=H&&Re(H),z=z||H.parent(),Z(W,z,H),L.push(W,"enter",Or(ne))},move:function(W,z,H,ne){return z=z&&Re(z),H=H&&Re(H),z=z||H.parent(),Z(W,z,H),L.push(W,"move",Or(ne))},leave:function(W,z){return L.push(W,"leave",Or(z),function(){W.remove()})},addClass:function(W,z,H){return H=Or(H),H.addClass=$i(H.addclass,z),L.push(W,"addClass",H)},removeClass:function(W,z,H){return H=Or(H),H.removeClass=$i(H.removeClass,z),L.push(W,"removeClass",H)},setClass:function(W,z,H,ne){return ne=Or(ne),ne.addClass=$i(ne.addClass,z),ne.removeClass=$i(ne.removeClass,H),L.push(W,"setClass",ne)},animate:function(W,z,H,ne,ie){return ie=Or(ie),ie.from=ie.from?e(ie.from,z):z,ie.to=ie.to?e(ie.t Line truncated
`,nt);Ge.$apply(function(){for(var Me=0,We=Jt.length;Me<We;++Me)try{Jt[Me]()}catch(it){ye(it)}Jt=void 0})}finally{It++}}function un(Me,We){if(!Me)return Me;if(!X(Me))throw Yn("srcset",'Can\'t pass trusted values to `{0}`: "{1}"',We,Me.toString());for(var it="",dt=we(Me),$t=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,At=/\s/.test(dt)?$t:/(,)/,Mt=dt.split(At),an=Math.floor(Mt.length/2),Lt=0;Lt<an;Lt++){var Bt=Lt*2;it+=at.getTrustedMediaUrl(we(Mt[Bt])),it+=" "+we(Mt[Bt+1])}var Ut=we(Mt[Lt*2]).split(/\s/);return it+=at.getTrustedMediaUrl(we(Ut[0])),Ut.length===2&&(it+=" "+we(Ut[1])),it}function En(Me,We){if(We){var it=Object.keys(We),dt,$t,At;for(dt=0,$t=it.length;dt<$t;dt++)At=it[dt],this[At]=We[At]}else this.$attr={};this.$$element=Me}En.prototype={$normalize:Br,$addClass:function(Me){Me&&Me.length>0&&Je.addClass(this.$$element,Me)},$removeClass:function(Me){Me&&Me.length>0&&Je.removeClass(this.$$element,Me)},$updateClass:function(Me,We){var it=Ai(Me,We);it&&it.length&&Je.addClass(this.$$element,it);var dt=Ai(We,Me);dt&&dt.length&&Je.removeClass(this.$$element,dt)},$set:function(Me,We,it,dt){var $t=this.$$element[0],At=ui($t,Me),Mt=xi(Me),an=Me,Lt;At?(this.$$element.prop(Me,We),dt=At):Mt&&(this[Mt]=We,an=Mt),this[Me]=We,dt?this.$attr[Me]=dt:(dt=this.$attr[Me],dt||(this.$attr[Me]=dt=sn(Me,"-"))),Lt=st(this.$$element),Lt==="img"&&Me==="srcset"&&(this[Me]=We=un(We,"$set('srcset', value)")),it!==!1&&(We===null||E(We)?this.$$element.removeAttr(dt):lt.test(dt)?At&&We===!1?this.$$element.removeAttr(dt):this.$$element.attr(dt,We):An(this.$$element[0],dt,We));var Bt=this.$$observers;Bt&&n(Bt[an],function(Ut){try{Ut(We)}catch(zt){ye(zt)}})},$observe:function(Me,We){var it=this,dt=it.$$observers||(it.$$observers=Ft()),$t=dt[Me]||(dt[Me]=[]);return $t.push(We),Ge.$evalAsync(function(){!$t.$$inter&&it.hasOwnProperty(Me)&&!E(it[Me])&&We(it[Me])}),function(){Le($t,We)}}};function An(Me,We,it){xt.innerHTML="<span "+We+">";var dt=xt.firstChild.attributes,$t=dt[0];dt.removeNamedItem($t.name),$t.value=it,Me.attributes.setNamedItem($t)}function On(Me,We){try{Me.addClass(We)}catch{}}var Gn=He.startSymbol(),jn=He.endSymbol(),pr=Gn==="{{"&&jn==="}}"?S:function(We){return We.replace(/\{\{/g,Gn).replace(/}}/g,jn)},nr=/^ng(Attr|Prop|On)([A-Z].*)$/,hr=/^(.+)Start$/;return Wn.$$addBindingInfo=tt?function(We,it){var dt=We.data("$binding")||[];G(it)?dt=dt.concat(it):dt.push(it),We.data("$binding",dt)}:g,Wn.$$addBindingClass=tt?function(We){On(We,"ng-binding")}:g,Wn.$$addScopeInfo=tt?function(We,it,dt,$t){var At=dt?$t?"$isolateScopeNoTemplate":"$isolateScope":"$scope";We.data(At,it)}:g,Wn.$$addScopeClass=tt?function(We,it){On(We,it?"ng-isolate-scope":"ng-scope")}:g,Wn.$$createComment=function(Me,We){var it="";return tt&&(it=" "+(Me||"")+": ",We&&(it+=We+" ")),yt.document.createComment(it)},Wn;function Wn(Me,We,it,dt,$t){Me instanceof Re||(Me=Re(Me));var At=Li(Me,We,Me,it,dt,$t);Wn.$$addScopeClass(Me);var Mt=null;return function(Lt,Bt,Ut){if(!Me)throw Yn("multilink","This element has already been linked.");on(Lt,"scope"),$t&&$t.needsNewScope&&(Lt=Lt.$parent.$new()),Ut=Ut||{};var zt=Ut.parentBoundTranscludeFn,Ct=Ut.transcludeControllers,Qt=Ut.futureParentElement;zt&&zt.$$boundTransclude&&(zt=zt.$$boundTransclude),Mt||(Mt=Mi(Qt));var yn;if(Mt!=="html"?yn=Re(Kc(Mt,Re("<div></div>").append(Me).html())):Bt?yn=hi.clone.call(Me):yn=Me,Ct)for(var Pn in Ct)yn.data("$"+Pn+"Controller",Ct[Pn].instance);return Wn.$$addScopeInfo(yn,Lt),Bt&&Bt(yn,Lt),At&&At(Lt,yn,yn,zt),Bt||(Me=At=null),yn}}function Mi(Me){var We=Me&&Me[0];return We&&st(We)!=="foreignobject"&&_.call(We).match(/SVG/)?"svg":"html"}function Li(Me,We,it,dt,$t,At){for(var Mt=[],an=G(Me)||Me instanceof Re,Lt,Bt,Ut,zt,Ct,Qt,yn,Pn=0;Pn<Me.length;Pn++)Lt=new En,Ye===11&&Yc(Me,Pn,an),Bt=bi(Me[Pn],[],Lt,Pn===0?dt:void 0,$t),Ut=Bt.length?If(Bt,Me[Pn],Lt,We,it,null,[],[],At):null,Ut&&Ut.scope&&Wn.$$addScopeClass(Lt.$$element),Ct=Ut&&Ut.terminal||!(zt=Me[Pn].childNodes)||!zt.length?null:Li(zt,Ut?(Ut.transcludeOnThisElement||!Ut.templateOnThisElement)&&Ut.transclude:We),(Ut||Ct)&&(Mt.push(Pn,Ut,Ct),Qt=!0,yn=yn||Ut),At=null;return Qt?Rn:null;function Rn(_n,wn,Nt,Cn){var Tn,Kn,Xn,qn,Dn,mr,ir,xr,ei;if(yn){var ms=wn.length;for(ei=new Array(ms),Dn=0;Dn<Mt.length;Dn+=3)ir=Mt[Dn],ei[ir]=wn[ir]}else ei=wn;for(Dn=0,mr=Mt.length;Dn<mr;)Xn=ei[Mt[Dn++]],Tn=Mt[Dn++],Kn=Mt[Dn++],Tn?(Tn.scope?(qn=_n.$new(),Wn.$$addScopeInfo(Re(Xn),qn)):qn=_n,Tn.transcludeOnThisElement?xr=qr(_n,Tn.transclude,Cn):!Tn.templateOnThisElement&&Cn?xr=Cn:!Cn&&We?xr=qr(_n,We):xr=null,Tn(Kn,qn,Xn,Nt,xr)):Kn&&Kn(_n,Xn.childNodes,void 0,Cn)}}function Yc(Me,We,it){var dt=Me[We],$t=dt.parentNode,At;if(dt.nodeType===nn)for(;At=$t?dt.nextSibling:Me[We+1],!(!At||At.nodeType!==nn);)dt.nodeValue=dt.nodeValue+At.nodeValue,At.parentNode&&At.parentNode.removeChild(At),it&&At===Me[We+1]&&Me.splice(We+1,1)}function qr(Me,We,it){function dt(Mt,an,Lt,Bt,Ut){return Mt||(Mt=Me.$new(!1,Ut),Mt.$$transcluded=!0),We(Mt,an,{parentBoundTranscludeFn:it,transcludeController Line truncated
`),function(L){w=L.indexOf(":"),A(Ce(we(L.substr(0,w))),we(L.substr(w+1)))}):U(t)&&n(t,function(L,Z){A(Ce(Z),we(L))}),d}function Pr(t){var d;return function(w){if(d||(d=yo(t)),w){var A=d[Ce(w)];return A===void 0&&(A=null),A}return d}}function Jr(t,d,w,A){return B(A)?A(t,d,w):(n(A,function(L){t=L(t,d,w)}),t)}function ns(t){return 200<=t&&t<300}function Na(){var t=this.defaults={transformResponse:[ts],transformRequest:[function(L){return U(L)&&!N(L)&&!D(L)&&!V(L)?Pe(L):L}],headers:{common:{Accept:"application/json, text/plain, */*"},post:se(Os),put:se(Os),patch:se(Os)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer",jsonpCallbackParam:"callback"},d=!1;this.useApplyAsync=function(L){return x(L)?(d=!!L,this):d};var w=this.interceptors=[],A=this.xsrfTrustedOrigins=[];Object.defineProperty(this,"xsrfWhitelistedOrigins",{get:function(){return this.xsrfTrustedOrigins},set:function(L){this.xsrfTrustedOrigins=L}}),this.$get=["$browser","$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector","$sce",function(L,Z,W,z,H,ne,ie,ce){var de=z("$http");t.paramSerializer=X(t.paramSerializer)?ie.get(t.paramSerializer):t.paramSerializer;var Ee=[];n(w,function(Oe){Ee.unshift(X(Oe)?ie.get(Oe):ie.invoke(Oe))});var Se=Ho(A);function tt(Oe){if(!U(Oe))throw rt("$http")("badreq","Http request configuration must be an object. Received: {0}",Oe);if(!X(ce.valueOf(Oe.url)))throw rt("$http")("badreq","Http request configuration url must be a string or a $sce trusted object. Received: {0}",Oe.url);var He=e({method:"get",transformRequest:t.transformRequest,transformResponse:t.transformResponse,paramSerializer:t.paramSerializer,jsonpCallbackParam:t.jsonpCallbackParam},Oe);He.headers=Je(Oe),He.method=$(He.method),He.paramSerializer=X(He.paramSerializer)?ie.get(He.paramSerializer):He.paramSerializer,L.$$incOutstandingRequestCount("$http");var ye=[],ge=[],$e=ne.resolve(He);return n(Ee,function(Tt){(Tt.request||Tt.requestError)&&ye.unshift(Tt.request,Tt.requestError),(Tt.response||Tt.responseError)&&ge.push(Tt.response,Tt.responseError)}),$e=ke($e,ye),$e=$e.then(lt),$e=ke($e,ge),$e=$e.finally(Ge),$e;function ke(Tt,wt){for(var It=0,Jt=wt.length;It<Jt;){var Yt=wt[It++],un=wt[It++];Tt=Tt.then(Yt,un)}return wt.length=0,Tt}function Ge(){L.$$completeOutstandingRequest(g,"$http")}function at(Tt,wt){var It,Jt={};return n(Tt,function(Yt,un){B(Yt)?(It=Yt(wt),It!=null&&(Jt[un]=It)):Jt[un]=Yt}),Jt}function Je(Tt){var wt=t.headers,It=e({},Tt.headers),Jt,Yt,un;wt=e({},wt.common,wt[Ce(Tt.method)]);e:for(Jt in wt){Yt=Ce(Jt);for(un in It)if(Ce(un)===Yt)continue e;It[Jt]=wt[Jt]}return at(It,se(Tt))}function lt(Tt){var wt=Tt.headers,It=Jr(Tt.data,Pr(wt),void 0,Tt.transformRequest);return E(It)&&n(wt,function(Jt,Yt){Ce(Yt)==="content-type"&&delete wt[Yt]}),E(Tt.withCredentials)&&!E(t.withCredentials)&&(Tt.withCredentials=t.withCredentials),et(Tt,It).then(xt,xt)}function xt(Tt){var wt=e({},Tt);return wt.data=Jr(Tt.data,Tt.headers,Tt.status,He.transformResponse),ns(Tt.status)?wt:ne.reject(wt)}}return tt.pendingRequests=[],mt("get","delete","head","jsonp"),nt("post","put","patch"),tt.defaults=t,tt;function mt(Oe){n(arguments,function(He){tt[He]=function(ye,ge){return tt(e({},ge||{},{method:He,url:ye}))}})}function nt(Oe){n(arguments,function(He){tt[He]=function(ye,ge,$e){return tt(e({},$e||{},{method:He,url:ye,data:ge}))}})}function et(Oe,He){var ye=ne.defer(),ge=ye.promise,$e,ke,Ge=Oe.headers,at=Ce(Oe.method)==="jsonp",Je=Oe.url;if(at?Je=ce.getTrustedResourceUrl(Je):X(Je)||(Je=ce.valueOf(Je)),Je=Qe(Je,Oe.paramSerializer(Oe.params)),at&&(Je=ot(Je,Oe.jsonpCallbackParam)),tt.pendingRequests.push(Oe),ge.then(Jt,Jt),(Oe.cache||t.cache)&&Oe.cache!==!1&&(Oe.method==="GET"||Oe.method==="JSONP")&&($e=U(Oe.cache)?Oe.cache:U(t.cache)?t.cache:de),$e&&(ke=$e.get(Je),x(ke)?te(ke)?ke.then(It,It):G(ke)?wt(ke[1],ke[0],se(ke[2]),ke[3],ke[4]):wt(ke,200,{},"OK","complete"):$e.put(Je,ge)),E(ke)){var lt=Se(Oe.url)?W()[Oe.xsrfCookieName||t.xsrfCookieName]:void 0;lt&&(Ge[Oe.xsrfHeaderName||t.xsrfHeaderName]=lt),Z(Oe.method,Je,He,Tt,Ge,Oe.timeout,Oe.withCredentials,Oe.responseType,xt(Oe.eventHandlers),xt(Oe.uploadEventHandlers))}return ge;function xt(Yt){if(Yt){var un={};return n(Yt,function(En,An){un[An]=function(On){d?H.$applyAsync(Gn):H.$$phase?Gn():H.$apply(Gn);function Gn(){En(On)}}}),un}}function Tt(Yt,un,En,An,On){$e&&(ns(Yt)?$e.put(Je,[Yt,un,yo(En),An,On]):$e.remove(Je));function Gn(){wt(un,Yt,En,An,On)}d?H.$applyAsync(Gn):(Gn(),H.$$phase||H.$apply())}function wt(Yt,un,En,An,On){un=un>=-1?un:0,(ns(un)?ye.resolve:ye.reject)({data:Yt,status:un,headers:Pr(En),config:Oe,statusText:An,xhrStatus:On})}function It(Yt){wt(Yt.data,Yt.status,se(Yt.headers()),Yt.statusText,Yt.xhrStatus)}function Jt(){var Yt=tt.pendingRequests.indexOf(Oe);Yt!==-1&&tt.pendingRequests.splice(Yt,1)}}function Qe(Oe,He){return He.length>0&&(Oe+=(Oe.indexOf("?")===-1?"?":"&")+He),Oe}function ot(Oe,He){var ye=Oe.split("?");if(ye.length>2)throw es("b Line truncated
Strict Contextual Escaping disallows interpolations that concatenate multiple expressions when a trusted value is required. See http://docs.angularjs.org/api/ng.$sce`,t)},ri.interr=function(t,d){return ri("interr",`Can't interpolate: {0}
{1}`,t,d.toString())};function Eo(){var t="{{",d="}}";this.startSymbol=function(w){return w?(t=w,this):t},this.endSymbol=function(w){return w?(d=w,this):d},this.$get=["$parse","$exceptionHandler","$sce",function(w,A,L){var Z=t.length,W=d.length,z=new RegExp(t.replace(/./g,ne),"g"),H=new RegExp(d.replace(/./g,ne),"g");function ne(Ee){return"\\\\\\"+Ee}function ie(Ee){return Ee.replace(z,t).replace(H,d)}function ce(Ee,Se,tt,mt){var nt=Ee.$watch(function(Qe){return nt(),mt(Qe)},Se,tt);return nt}function de(Ee,Se,tt,mt){var nt=tt===L.URL||tt===L.MEDIA_URL;if(!Ee.length||Ee.indexOf(t)===-1){if(Se)return;var et=ie(Ee);nt&&(et=L.getTrusted(tt,et));var Qe=k(et);return Qe.exp=Ee,Qe.expressions=[],Qe.$$watchDelegate=ce,Qe}mt=!!mt;for(var ot,Oe,He=0,ye=[],ge,$e=Ee.length,ke,Ge=[],at=[],Je;He<$e;)if((ot=Ee.indexOf(t,He))!==-1&&(Oe=Ee.indexOf(d,ot+Z))!==-1)He!==ot&&Ge.push(ie(Ee.substring(He,ot))),ke=Ee.substring(ot+Z,Oe),ye.push(ke),He=Oe+W,at.push(Ge.length),Ge.push("");else{He!==$e&&Ge.push(ie(Ee.substring(He)));break}Je=Ge.length===1&&at.length===1;var lt=nt&&Je?void 0:Tt;if(ge=ye.map(function(wt){return w(wt,lt)}),!Se||ye.length){var xt=function(wt){for(var It=0,Jt=ye.length;It<Jt;It++){if(mt&&E(wt[It]))return;Ge[at[It]]=wt[It]}return nt?L.getTrusted(tt,Je?Ge[0]:Ge.join("")):(tt&&Ge.length>1&&ri.throwNoconcat(Ee),Ge.join(""))};return e(function(It){var Jt=0,Yt=ye.length,un=new Array(Yt);try{for(;Jt<Yt;Jt++)un[Jt]=ge[Jt](It);return xt(un)}catch(En){A(ri.interr(Ee,En))}},{exp:Ee,expressions:ye,$$watchDelegate:function(wt,It){var Jt;return wt.$watchGroup(ge,function(un,En){var An=xt(un);It.call(this,An,un!==En?Jt:An,wt),Jt=An})}})}function Tt(wt){try{return wt=tt&&!nt?L.getTrusted(tt,wt):L.valueOf(wt),mt&&!x(wt)?wt:ln(wt)}catch(It){A(ri.interr(Ee,It))}}}return de.startSymbol=function(){return t},de.endSymbol=function(){return d},de}]}var ja=rt("$interval");function Ha(){this.$get=["$$intervalFactory","$window",function(t,d){var w={},A=function(W,z,H){var ne=d.setInterval(W,z);return w[ne]=H,ne},L=function(W){d.clearInterval(W),delete w[W]},Z=t(A,L);return Z.cancel=function(W){if(!W)return!1;if(!W.hasOwnProperty("$$intervalId"))throw ja("badprom","`$interval.cancel()` called with a promise that was not generated by `$interval()`.");if(!w.hasOwnProperty(W.$$intervalId))return!1;var z=W.$$intervalId,H=w[z];return ss(H.promise),H.reject("canceled"),L(z),!0},Z}]}function za(){this.$get=["$browser","$q","$$q","$rootScope",function(t,d,w,A){return function(Z,W){return function(H,ne,ie,ce){var de=arguments.length>4,Ee=de?J(arguments,4):[],Se=0,tt=x(ce)&&!ce,mt=(tt?w:d).defer(),nt=mt.promise;ie=x(ie)?ie:0;function et(){de?H.apply(null,Ee):H(Se)}function Qe(){tt?t.defer(et):A.$evalAsync(et),mt.notify(Se++),ie>0&&Se>=ie&&(mt.resolve(Se),W(nt.$$intervalId)),tt||A.$apply()}return nt.$$intervalId=Z(Qe,ne,mt,tt),nt}}}]}var Wa=function(){this.$get=function(){var t=l.callbacks,d={};function w(A){var L=function(Z){L.data=Z,L.called=!0};return L.id=A,L}return{createCallback:function(A){var L="_"+(t.$$counter++).toString(36),Z="angular.callbacks."+L,W=w(L);return d[Z]=t[L]=W,Z},wasCalled:function(A){return d[A].called},getResponse:function(A){return d[A].data},removeCallback:function(A){var L=d[A];delete t[L.id],delete d[A]}}}},Va=/^([^?#]*)(\?([^#]*))?(#(.*))?$/,Ya={http:80,https:443,ftp:21},Ci=rt("$location");function Ga(t){for(var d=t.split("/"),w=d.length;w--;)d[w]=Vt(d[w].replace(/%2F/g,"/"));return d.join("/")}function qa(t,d){for(var w=t.split("/"),A=w.length;A--;)w[A]=decodeURIComponent(w[A]),d&&(w[A]=w[A].replace(/\//g,"%2F"));return w.join("/")}function Ka(t,d,w){var A=Et(d),L=w?"#"+Vt(w):"",Z=Ga(t);return Z+(A?"?"+A:"")+L}function So(t,d){var w=St(t);d.$$protocol=w.protocol,d.$$host=w.hostname,d.$$port=i(w.port)||Ya[w.protocol]||null}var Xa=/^\s*[\\/]{2,}/;function xo(t,d,w){if(Xa.test(t))throw Ci("badpath",'Invalid url "{0}".',t);var A=t.charAt(0)!=="/";A&&(t="/"+t);var L=St(t),Z=A&&L.pathname.charAt(0)==="/"?L.pathname.substring(1):L.pathname;d.$$path=qa(Z,w),d.$$search=vn(L.search),d.$$hash=decodeURIComponent(L.hash),d.$$path&&d.$$path.charAt(0)!=="/"&&(d.$$path="/"+d.$$path)}function Ds(t,d){return t.slice(0,d.length)===d}function Dr(t,d){if(Ds(d,t))return d.substr(t.length)}function ii(t){var d=t.indexOf("#");return d===-1?t:t.substr(0,d)}function Za(t){return t.substr(0,ii(t).lastIndexOf("/")+1)}function Ja(t){return t.substring(0,t.indexOf("/",t.indexOf("//")+2))}function Ms(t,d,w){this.$$html5=!0,w=w||"",So(t,this),this.$$parse=function(A){var L=Dr(d,A);if(!X(L))throw Ci("ipthprfx",'Invalid url "{0}", missing path prefix "{1}".',A,d);xo(L,this,!0),this.$$path||(this.$$path="/"),this.$$compose()},this.$$normalizeUrl=function(A){return d+A.substr(1)},this.$$parseLinkUrl=function(A,L){if(L&&L[0]==="#")return this.hash(L.slice(1)),!0;var Z,W,z;return x(Z=Dr(t,A))?(W=Z,w&&x(Z=Dr(w,Z))?z=d+(Dr("/",Z)||Z):z=t+W):x(Z=Dr(d,A))?z=d+Z:d===A+"/"&&(z=d),z&&this.$$parse(z),!!z}}function Ls(t,d,w){So(t,this),this.$$parse=function(A) Line truncated
`+W.stack:W.stack:W.sourceURL&&(W=W.message+`
`+W.sourceURL+":"+W.line)),W}function Z(W){var z=w.console||{},H=z[W]||z.log||g;return function(){var ne=[];return n(arguments,function(ie){ne.push(L(ie))}),Function.prototype.apply.call(H,z,ne)}}}]}var Gr=rt("$parse"),li={}.constructor.prototype.valueOf;function Ri(t){return t+""}var Ii=Ft();n("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(t){Ii[t]=!0});var pi={n:`
`,f:"\f",r:"\r",t:" ",v:"\v","'":"'",'"':'"'},Oi=function(d){this.options=d};Oi.prototype={constructor:Oi,lex:function(t){for(this.text=t,this.index=0,this.tokens=[];this.index<this.text.length;){var d=this.text.charAt(this.index);if(d==='"'||d==="'")this.readString(d);else if(this.isNumber(d)||d==="."&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdentifierStart(this.peekMultichar()))this.readIdent();else if(this.is(d,"(){}[].,;:?"))this.tokens.push({index:this.index,text:d}),this.index++;else if(this.isWhitespace(d))this.index++;else{var w=d+this.peek(),A=w+this.peek(2),L=Ii[d],Z=Ii[w],W=Ii[A];if(L||Z||W){var z=W?A:Z?w:d;this.tokens.push({index:this.index,text:z,operator:!0}),this.index+=z.length}else this.throwError("Unexpected next character ",this.index,this.index+1)}}return this.tokens},is:function(t,d){return d.indexOf(t)!==-1},peek:function(t){var d=t||1;return this.index+d<this.text.length?this.text.charAt(this.index+d):!1},isNumber:function(t){return"0"<=t&&t<="9"&&typeof t=="string"},isWhitespace:function(t){return t===" "||t==="\r"||t===" "||t===`
`||t==="\v"||t==="\xA0"},isIdentifierStart:function(t){return this.options.isIdentifierStart?this.options.isIdentifierStart(t,this.codePointAt(t)):this.isValidIdentifierStart(t)},isValidIdentifierStart:function(t){return"a"<=t&&t<="z"||"A"<=t&&t<="Z"||t==="_"||t==="$"},isIdentifierContinue:function(t){return this.options.isIdentifierContinue?this.options.isIdentifierContinue(t,this.codePointAt(t)):this.isValidIdentifierContinue(t)},isValidIdentifierContinue:function(t,d){return this.isValidIdentifierStart(t,d)||this.isNumber(t)},codePointAt:function(t){return t.length===1?t.charCodeAt(0):(t.charCodeAt(0)<<10)+t.charCodeAt(1)-56613888},peekMultichar:function(){var t=this.text.charAt(this.index),d=this.peek();if(!d)return t;var w=t.charCodeAt(0),A=d.charCodeAt(0);return w>=55296&&w<=56319&&A>=56320&&A<=57343?t+d:t},isExpOperator:function(t){return t==="-"||t==="+"||this.isNumber(t)},throwError:function(t,d,w){w=w||this.index;var A=x(d)?"s "+d+"-"+this.index+" ["+this.text.substring(d,w)+"]":" "+w;throw Gr("lexerr","Lexer Error: {0} at column{1} in expression [{2}].",t,A,this.text)},readNumber:function(){for(var t="",d=this.index;this.index<this.text.length;){var w=Ce(this.text.charAt(this.index));if(w==="."||this.isNumber(w))t+=w;else{var A=this.peek();if(w==="e"&&this.isExpOperator(A))t+=w;else if(this.isExpOperator(w)&&A&&this.isNumber(A)&&t.charAt(t.length-1)==="e")t+=w;else if(this.isExpOperator(w)&&(!A||!this.isNumber(A))&&t.charAt(t.length-1)==="e")this.throwError("Invalid exponent");else break}this.index++}this.tokens.push({index:d,text:t,constant:!0,value:Number(t)})},readIdent:function(){var t=this.index;for(this.index+=this.peekMultichar().length;this.index<this.text.length;){var d=this.peekMultichar();if(!this.isIdentifierContinue(d))break;this.index+=d.length}this.tokens.push({index:t,text:this.text.slice(t,this.index),identifier:!0})},readString:function(t){var d=this.index;this.index++;for(var w="",A=t,L=!1;this.index<this.text.length;){var Z=this.text.charAt(this.index);if(A+=Z,L){if(Z==="u"){var W=this.text.substring(this.index+1,this.index+5);W.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+W+"]"),this.index+=4,w+=String.fromCharCode(parseInt(W,16))}else{var z=pi[Z];w=w+(z||Z)}L=!1}else if(Z==="\\")L=!0;else if(Z===t){this.index++,this.tokens.push({index:d,text:A,constant:!0,value:w});return}else w+=Z;this.index++}this.throwError("Unterminated quote",d)}};var kt=function(d,w){this.lexer=d,this.options=w};kt.Program="Program",kt.ExpressionStatement="ExpressionStatement",kt.AssignmentExpression="AssignmentExpression",kt.ConditionalExpression="ConditionalExpression",kt.LogicalExpression="LogicalExpression",kt.BinaryExpression="BinaryExpression",kt.UnaryExpression="UnaryExpression",kt.CallExpression="CallExpression",kt.MemberExpression="MemberExpression",kt.Identifier="Identifier",kt.Literal="Literal",kt.ArrayExpression="ArrayExpression",kt.Property="Property",kt.ObjectExpression="ObjectExpression",kt.ThisExpression="ThisExpression",kt.LocalsExpression="LocalsExpression",kt.NGValueParameter="NGValueParameter",kt.prototype={ast:function(t){this.text=t,this.tokens=this.lexer.lex(t);var d=this.program();return this.tokens.length!==0&&this.throwError("is an unexpected token",this.tokens[0]),d},program:function(){for(var t=[];;)if(this.tokens.length>0&&!this.peek("}",")",";","]")&&t.push(this.expressionStatement()),!this.expect(";"))return{type:kt.Program,body:t}},expressionStatement:function(){return{type:kt.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var t=this.expression();this.expect("|");)t=this.filter(t);return t},expression:function(){return this.assignment()},assignment:function(){var t=this.ternary();if(this.expect("=")){if(!Oo(t))throw Gr("lval","Trying to assign a value to a non l-value");t={type:kt.AssignmentExpression,left:t,right:this.assignment(),operator:"="}}return t},ternary:function(){var t=this.logicalOR(),d,w;return this.expect("?")&&(d=this.expression(),this.consume(":"))?(w=this.expression(),{type:kt.ConditionalExpression,test:t,alternate:d,consequent:w}):t},logicalOR:function(){for(var t=this.logicalAND();this.expect("||");)t={type:kt.LogicalExpression,operator:"||",left:t,right:this.logicalAND()};return t},logicalAND:function(){for(var t=this.equality();this.expect("&&");)t={type:kt.LogicalExpression,operator:"&&",left:t,right:this.equality()};return t},equality:function(){for(var t=this.relational(),d;d=this.expect("==","!=","===","!==");)t={type:kt.BinaryExpression,operator:d.text,left:t,right:this.relational()};return t},relational:function(){for(var t=this.additive(),d;d=this.expect("<",">","<=",">=");)t={type:kt.BinaryExpression,operator:d.text,left:t,right:this.additive()};return t},additive:function(){for(var t=this.multiplicative(),d;d=this.expect("+","-");)t={type:kt.BinaryExpression,operator:d.text,left:t,right:this.multiplicative()};return t},multiplicative:function(){for(var t=this.unary(),d;d=this.expect("*" Line truncated
`+this.filterPrefix()+"var fn="+this.generateFunction("fn","s,l,a,i")+w+this.watchFns()+"return fn;",z=new Function("$filter","getStringValue","ifDefined","plus",W)(this.$filter,Ri,ec,To);return this.state=this.stage=void 0,z},USE:"use",STRICT:"strict",watchFns:function(){var t=[],d=this.state.inputs,w=this;return n(d,function(A){t.push("var "+A.name+"="+w.generateFunction(A.name,"s")),A.isPure&&t.push(A.name,".isPure="+JSON.stringify(A.isPure)+";")}),d.length&&t.push("fn.inputs=["+d.map(function(A){return A.name}).join(",")+"];"),t.join("")},generateFunction:function(t,d){return"function("+d+"){"+this.varsPrefix(t)+this.body(t)+"};"},filterPrefix:function(){var t=[],d=this;return n(this.state.filters,function(w,A){t.push(w+"=$filter("+d.escape(A)+")")}),t.length?"var "+t.join(",")+";":""},varsPrefix:function(t){return this.state[t].vars.length?"var "+this.state[t].vars.join(",")+";":""},body:function(t){return this.state[t].body.join("")},recurse:function(t,d,w,A,L,Z){var W,z,H=this,ne,ie,ce;if(A=A||g,!Z&&x(t.watchId)){d=d||this.nextId(),this.if_("i",this.lazyAssign(d,this.computedMember("i",t.watchId)),this.lazyRecurse(t,d,w,A,L,!0));return}switch(t.type){case kt.Program:n(t.body,function(de,Ee){H.recurse(de.expression,void 0,void 0,function(Se){z=Se}),Ee!==t.body.length-1?H.current().body.push(z,";"):H.return_(z)});break;case kt.Literal:ie=this.escape(t.value),this.assign(d,ie),A(d||ie);break;case kt.UnaryExpression:this.recurse(t.argument,void 0,void 0,function(de){z=de}),ie=t.operator+"("+this.ifDefined(z,0)+")",this.assign(d,ie),A(ie);break;case kt.BinaryExpression:this.recurse(t.left,void 0,void 0,function(de){W=de}),this.recurse(t.right,void 0,void 0,function(de){z=de}),t.operator==="+"?ie=this.plus(W,z):t.operator==="-"?ie=this.ifDefined(W,0)+t.operator+this.ifDefined(z,0):ie="("+W+")"+t.operator+"("+z+")",this.assign(d,ie),A(ie);break;case kt.LogicalExpression:d=d||this.nextId(),H.recurse(t.left,d),H.if_(t.operator==="&&"?d:H.not(d),H.lazyRecurse(t.right,d)),A(d);break;case kt.ConditionalExpression:d=d||this.nextId(),H.recurse(t.test,d),H.if_(d,H.lazyRecurse(t.alternate,d),H.lazyRecurse(t.consequent,d)),A(d);break;case kt.Identifier:d=d||this.nextId(),w&&(w.context=H.stage==="inputs"?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",t.name)+"?l:s"),w.computed=!1,w.name=t.name),H.if_(H.stage==="inputs"||H.not(H.getHasOwnProperty("l",t.name)),function(){H.if_(H.stage==="inputs"||"s",function(){L&&L!==1&&H.if_(H.isNull(H.nonComputedMember("s",t.name)),H.lazyAssign(H.nonComputedMember("s",t.name),"{}")),H.assign(d,H.nonComputedMember("s",t.name))})},d&&H.lazyAssign(d,H.nonComputedMember("l",t.name))),A(d);break;case kt.MemberExpression:W=w&&(w.context=this.nextId())||this.nextId(),d=d||this.nextId(),H.recurse(t.object,W,void 0,function(){H.if_(H.notNull(W),function(){t.computed?(z=H.nextId(),H.recurse(t.property,z),H.getStringValue(z),L&&L!==1&&H.if_(H.not(H.computedMember(W,z)),H.lazyAssign(H.computedMember(W,z),"{}")),ie=H.computedMember(W,z),H.assign(d,ie),w&&(w.computed=!0,w.name=z)):(L&&L!==1&&H.if_(H.isNull(H.nonComputedMember(W,t.property.name)),H.lazyAssign(H.nonComputedMember(W,t.property.name),"{}")),ie=H.nonComputedMember(W,t.property.name),H.assign(d,ie),w&&(w.computed=!1,w.name=t.property.name))},function(){H.assign(d,"undefined")}),A(d)},!!L);break;case kt.CallExpression:d=d||this.nextId(),t.filter?(z=H.filter(t.callee.name),ne=[],n(t.arguments,function(de){var Ee=H.nextId();H.recurse(de,Ee),ne.push(Ee)}),ie=z+"("+ne.join(",")+")",H.assign(d,ie),A(d)):(z=H.nextId(),W={},ne=[],H.recurse(t.callee,z,W,function(){H.if_(H.notNull(z),function(){n(t.arguments,function(de){H.recurse(de,t.constant?void 0:H.nextId(),void 0,function(Ee){ne.push(Ee)})}),W.name?ie=H.member(W.context,W.name,W.computed)+"("+ne.join(",")+")":ie=z+"("+ne.join(",")+")",H.assign(d,ie)},function(){H.assign(d,"undefined")}),A(d)}));break;case kt.AssignmentExpression:z=this.nextId(),W={},this.recurse(t.left,void 0,W,function(){H.if_(H.notNull(W.context),function(){H.recurse(t.right,z),ie=H.member(W.context,W.name,W.computed)+t.operator+z,H.assign(d,ie),A(d||ie)})},1);break;case kt.ArrayExpression:ne=[],n(t.elements,function(de){H.recurse(de,t.constant?void 0:H.nextId(),void 0,function(Ee){ne.push(Ee)})}),ie="["+ne.join(",")+"]",this.assign(d,ie),A(d||ie);break;case kt.ObjectExpression:ne=[],ce=!1,n(t.properties,function(de){de.computed&&(ce=!0)}),ce?(d=d||this.nextId(),this.assign(d,"{}"),n(t.properties,function(de){de.computed?(W=H.nextId(),H.recurse(de.key,W)):W=de.key.type===kt.Identifier?de.key.name:""+de.key.value,z=H.nextId(),H.recurse(de.value,z),H.assign(H.member(d,W,de.computed),z)})):(n(t.properties,function(de){H.recurse(de.value,t.constant?void 0:H.nextId(),void 0,function(Ee){ne.push(H.escape(de.key.type===kt.Identifier?de.key.name:""+de.key.value)+":"+Ee)})}),ie="{"+ne.join(",")+"}",this.assign(d,ie)),A(d||ie);break;case kt.ThisExpression:this.assign(d,"s"),A(d||"s");break;case kt.LocalsExpression:this.a Line truncated
Watchers fired in the last 5 iterations: {1}`,t,It)}while(Je||de.length);for(nt();tt<Ee.length;)try{Ee[tt++]()}catch(En){Z(En)}Ee.length=tt=0,z.$$checkUrlChange()},$suspend:function(){this.$$suspended=!0},$isSuspended:function(){return this.$$suspended},$resume:function(){this.$$suspended=!1},$destroy:function(){if(!this.$$destroyed){var ye=this.$parent;this.$broadcast("$destroy"),this.$$destroyed=!0,this===ce&&z.$$applicationDestroyed(),et(this,-this.$$watchersCount);for(var ge in this.$$listenerCount)Qe(this,this.$$listenerCount[ge],ge);ye&&ye.$$childHead===this&&(ye.$$childHead=this.$$nextSibling),ye&&ye.$$childTail===this&&(ye.$$childTail=this.$$prevSibling),this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling),this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling),this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=g,this.$on=this.$watch=this.$watchGroup=function(){return g},this.$$listeners={},this.$$nextSibling=null,ne(this)}},$eval:function(ye,ge){return W(ye)(this,ge)},$evalAsync:function(ye,ge){!ce.$$phase&&!de.length&&z.defer(function(){de.length&&ce.$digest()},null,"$evalAsync"),de.push({scope:this,fn:W(ye),locals:ge})},$$postDigest:function(ye){Ee.push(ye)},$apply:function(ye){try{mt("$apply");try{return this.$eval(ye)}finally{nt()}}catch(ge){Z(ge)}finally{try{ce.$digest()}catch(ge){throw Z(ge),ge}}},$applyAsync:function(ye){var ge=this;ye&&Se.push($e),ye=W(ye),He();function $e(){ge.$eval(ye)}},$on:function(ye,ge){var $e=this.$$listeners[ye];$e||(this.$$listeners[ye]=$e=[]),$e.push(ge);var ke=this;do ke.$$listenerCount[ye]||(ke.$$listenerCount[ye]=0),ke.$$listenerCount[ye]++;while(ke=ke.$parent);var Ge=this;return function(){var at=$e.indexOf(ge);at!==-1&&(delete $e[at],Qe(Ge,1,ye))}},$emit:function(ye,ge){var $e=[],ke,Ge=this,at=!1,Je={name:ye,targetScope:Ge,stopPropagation:function(){at=!0},preventDefault:function(){Je.defaultPrevented=!0},defaultPrevented:!1},lt=F([Je],arguments,1),xt,Tt;do{for(ke=Ge.$$listeners[ye]||$e,Je.currentScope=Ge,xt=0,Tt=ke.length;xt<Tt;xt++){if(!ke[xt]){ke.splice(xt,1),xt--,Tt--;continue}try{ke[xt].apply(null,lt)}catch(wt){Z(wt)}}if(at)break;Ge=Ge.$parent}while(Ge);return Je.currentScope=null,Je},$broadcast:function(ye,ge){var $e=this,ke=$e,Ge=$e,at={name:ye,targetScope:$e,preventDefault:function(){at.defaultPrevented=!0},defaultPrevented:!1};if(!$e.$$listenerCount[ye])return at;for(var Je=F([at],arguments,1),lt,xt,Tt;ke=Ge;){for(at.currentScope=ke,lt=ke.$$listeners[ye]||[],xt=0,Tt=lt.length;xt<Tt;xt++){if(!lt[xt]){lt.splice(xt,1),xt--,Tt--;continue}try{lt[xt].apply(null,Je)}catch(wt){Z(wt)}}if(!(Ge=ke.$$listenerCount[ye]&&ke.$$childHead||ke!==$e&&ke.$$nextSibling))for(;ke!==$e&&!(Ge=ke.$$nextSibling);)ke=ke.$parent}return at.currentScope=null,at}};var ce=new ie,de=ce.$$asyncQueue=[],Ee=ce.$$postDigestQueue=[],Se=ce.$$applyAsyncQueue=[],tt=0;return ce;function mt(ye){if(ce.$$phase)throw d("inprog","{0} already in progress",ce.$$phase);ce.$$phase=ye}function nt(){ce.$$phase=null}function et(ye,ge){do ye.$$watchersCount+=ge;while(ye=ye.$parent)}function Qe(ye,ge,$e){do ye.$$listenerCount[$e]-=ge,ye.$$listenerCount[$e]===0&&delete ye.$$listenerCount[$e];while(ye=ye.$parent)}function ot(){}function Oe(){for(;Se.length;)try{Se.shift()()}catch(ye){Z(ye)}A=null}function He(){A===null&&(A=z.defer(function(){ce.$apply(Oe)},null,"$applyAsync"))}}]}function hc(){var t=/^\s*(https?|s?ftp|mailto|tel|file):/,d=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationTrustedUrlList=function(w){return x(w)?(t=w,this):t},this.imgSrcSanitizationTrustedUrlList=function(w){return x(w)?(d=w,this):d},this.$get=function(){return function(A,L){var Z=L?d:t,W=St(A&&A.trim()).href;return W!==""&&!W.match(Z)?"unsafe:"+W:A}}}var Fr=rt("$sce"),Nn={HTML:"html",CSS:"css",MEDIA_URL:"mediaUrl",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},uc=/_([a-z])/g;function Fs(t){return t.replace(uc,yr)}function dc(t){if(t==="self")return t;if(X(t)){if(t.indexOf("***")>-1)throw Fr("iwcard","Illegal sequence *** in string matcher. String: {0}",t);return t=Be(t).replace(/\\\*\\\*/g,".*").replace(/\\\*/g,"[^:/.?&;]*"),new RegExp("^"+t+"$")}else{if(I(t))return new RegExp("^"+t.source+"$");throw Fr("imatcher",'Matchers may only be "self", string patterns or RegExp objects')}}function Uo(t){var d=[];return x(t)&&n(t,function(w){d.push(dc(w))}),d}function lc(){this.SCE_CONTEXTS=Nn;var t=["self"],d=[];this.trustedResourceUrlList=function(w){return arguments.length&&(t=Uo(w)),t},Object.defineProperty(this,"resourceUrlWhitelist",{get:function(){return this.trustedResourceUrlList},set:function(w){this.trustedResourceUrlList=w}}),this.bannedResourceUrlList=function(w){return arguments.length&&(d=Uo(w)),d},Object.defineProperty(this,"resourceUrlBlacklist",{get:function(){return this.bannedResourceUrlList},set:function(w){this.bannedResourceUrlList=w}}),this.$get=["$injector","$$sanitizeUri",function(w,A){var L=function(Se){throw Fr("unsafe","Attempting Line truncated
[`+De+"] ";for(ht in arguments[0])qe(arguments[0],ht)&&(he+=ht+": "+arguments[0][ht]+", ");he=he.slice(0,-2)}else he=arguments[De];re.push(he)}n(v+`
Arguments: `+Array.prototype.slice.call(re).join("")+`
`+new Error().stack),Q=!1}return O.apply(this,arguments)},O)}var o={};function a(v,O){Ke.deprecationHandler!=null&&Ke.deprecationHandler(v,O),o[v]||(n(O),o[v]=!0)}Ke.suppressDeprecationWarnings=!1,Ke.deprecationHandler=null;function f(v){return typeof Function!="undefined"&&v instanceof Function||Object.prototype.toString.call(v)==="[object Function]"}function s(v){var O,Q;for(Q in v)qe(v,Q)&&(O=v[Q],f(O)?this[Q]=O:this["_"+Q]=O);this._config=v,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)}function e(v,O){var Q=Re({},v),re;for(re in O)qe(O,re)&&(rt(v[re])&&rt(O[re])?(Q[re]={},Re(Q[re],v[re]),Re(Q[re],O[re])):O[re]!=null?Q[re]=O[re]:delete Q[re]);for(re in v)qe(v,re)&&!qe(O,re)&&rt(v[re])&&(Q[re]=Re({},Q[re]));return Q}function r(v){v!=null&&this.set(v)}var i;Object.keys?i=Object.keys:i=function(v){var O,Q=[];for(O in v)qe(v,O)&&Q.push(O);return Q};var c={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"};function h(v,O,Q){var re=this._calendar[v]||this._calendar.sameElse;return f(re)?re.call(O,Q):re}function g(v,O,Q){var re=""+Math.abs(v),he=O-re.length,De=v>=0;return(De?Q?"+":"":"-")+Math.pow(10,Math.max(0,he)).toString().substr(1)+re}var S=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,k=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,M={},E={};function x(v,O,Q,re){var he=re;typeof re=="string"&&(he=function(){return this[re]()}),v&&(E[v]=he),O&&(E[O[0]]=function(){return g(he.apply(this,arguments),O[1],O[2])}),Q&&(E[Q]=function(){return this.localeData().ordinal(he.apply(this,arguments),v)})}function U(v){return v.match(/\[[\s\S]/)?v.replace(/^\[|\]$/g,""):v.replace(/\\/g,"")}function j(v){var O=v.match(S),Q,re;for(Q=0,re=O.length;Q<re;Q++)E[O[Q]]?O[Q]=E[O[Q]]:O[Q]=U(O[Q]);return function(he){var De="",ht;for(ht=0;ht<re;ht++)De+=f(O[ht])?O[ht].call(he,v):O[ht];return De}}function X(v,O){return v.isValid()?(O=ee(O,v.localeData()),M[O]=M[O]||j(O),M[O](v)):v.localeData().invalidDate()}function ee(v,O){var Q=5;function re(he){return O.longDateFormat(he)||he}for(k.lastIndex=0;Q>=0&&k.test(v);)v=v.replace(k,re),k.lastIndex=0,Q-=1;return v}var ue={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"};function G(v){var O=this._longDateFormat[v],Q=this._longDateFormat[v.toUpperCase()];return O||!Q?O:(this._longDateFormat[v]=Q.match(S).map(function(re){return re==="MMMM"||re==="MM"||re==="DD"||re==="dddd"?re.slice(1):re}).join(""),this._longDateFormat[v])}var T="Invalid date";function B(){return this._invalidDate}var I="%d",b=/\d{1,2}/;function C(v){return this._ordinal.replace("%d",v)}var N={future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function V(v,O,Q,re){var he=this._relativeTime[Q];return f(he)?he(v,O,Q,re):he.replace(/%d/i,v)}function D(v,O){var Q=this._relativeTime[v>0?"future":"past"];return f(Q)?Q(O):Q.replace(/%s/i,O)}var Y={D:"date",dates:"date",date:"date",d:"day",days:"day",day:"day",e:"weekday",weekdays:"weekday",weekday:"weekday",E:"isoWeekday",isoweekdays:"isoWeekday",isoweekday:"isoWeekday",DDD:"dayOfYear",dayofyears:"dayOfYear",dayofyear:"dayOfYear",h:"hour",hours:"hour",hour:"hour",ms:"millisecond",milliseconds:"millisecond",millisecond:"millisecond",m:"minute",minutes:"minute",minute:"minute",M:"month",months:"month",month:"month",Q:"quarter",quarters:"quarter",quarter:"quarter",s:"second",seconds:"second",second:"second",gg:"weekYear",weekyears:"weekYear",weekyear:"weekYear",GG:"isoWeekYear",isoweekyears:"isoWeekYear",isoweekyear:"isoWeekYear",w:"week",weeks:"week",week:"week",W:"isoWeek",isoweeks:"isoWeek",isoweek:"isoWeek",y:"year",years:"year",year:"year"};function te(v){return typeof v=="string"?Y[v]||Y[v.toLowerCase()]:void 0}function pe(v){var O={},Q,re;for(re in v)qe(v,re)&&(Q=te(re),Q&&(O[Q]=v[re]));return O}var le={date:9,day:11,weekday:11,isoWeekday:11,dayOfYear:4,hour:13,millisecond:16,minute:14,month:8,quarter:7,second:15,weekYear:1,isoWeekYear:1,week:5,isoWeek:5,year:1};function be(v){var O=[],Q;for(Q in v)qe(v,Q)&&O.push({unit:Q,priority:le[Q]});return O.sort(function(re,he){return re.priority-he.priority}),O}var we=/\d/,Be=/\d\d/,Ze=/\d{3}/,gt=/\d{4}/,st=/[+-]?\d{6}/,_e=/\d\d?/,Le=/\d\d\d\d?/,ze=/\d\d\d\d\d\d?/,ft=/\d{1,3}/,Dt=/\d{1,4}/,q=/[+-]?\d{1,6}/,P=/\d+/,F=/[+-]?\d+/,J=/Z|[+-]\d\d:?\d\d/gi,oe=/Z|[+-]\d\d(?::?\d\d)?/gi,ve=/[+-]?\d+(\.\d{1,3})?/,Pe=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,Ie=/^[1-9] Line truncated
`)}},{"./der":19,inherits:147}],22:[function(_,K,R){(function(l,y){"use strict";function m(G,T){if(!G)throw new Error(T||"Assertion failed")}function p(G,T){G.super_=T;var B=function(){};B.prototype=T.prototype,G.prototype=new B,G.prototype.constructor=G}function n(G,T,B){return n.isBN(G)?G:(this.negative=0,this.words=null,this.length=0,this.red=null,void(G!==null&&((T==="le"||T==="be")&&(B=T,T=10),this._init(G||0,T||10,B||"be"))))}function u(G,T){var B=G.charCodeAt(T);return 65<=B&&70>=B?B-55:97<=B&&102>=B?B-87:15&B-48}function o(G,T,B){var I=u(G,B);return B-1>=T&&(I|=u(G,B-1)<<4),I}function a(G,T,B,I){for(var b=0,C=je(G.length,B),N=T,V;N<C;N++)V=G.charCodeAt(N)-48,b*=I,b+=49<=V?V-49+10:17<=V?V-17+10:V;return b}function f(G){for(var T=Array(G.bitLength()),B=0;B<T.length;B++){var I=0|B/26,b=B%26;T[B]=(G.words[I]&1<<b)>>>b}return T}function s(G,T,B){B.negative=T.negative^G.negative;var I=0|G.length+T.length;B.length=I,I=0|I-1;var b=0|G.words[0],C=0|T.words[0],N=b*C,V=67108863&N,D=0|N/67108864;B.words[0]=V;for(var Y=1;Y<I;Y++){for(var te=D>>>26,pe=67108863&D,le=je(Y,T.length-1),be=Xe(0,Y-G.length+1),we;be<=le;be++)we=0|Y-be,b=0|G.words[we],C=0|T.words[be],N=b*C+pe,te+=0|N/67108864,pe=67108863&N;B.words[Y]=0|pe,D=0|te}return D===0?B.length--:B.words[Y]=0|D,B.strip()}function e(G,T,B){B.negative=T.negative^G.negative,B.length=G.length+T.length;for(var I=0,b=0,C=0,N;C<B.length-1;C++){N=b,b=0;for(var V=67108863&I,D=je(C,T.length-1),Y=Xe(0,C-G.length+1);Y<=D;Y++){var te=C-Y,pe=0|G.words[te],le=0|T.words[Y],be=pe*le,we=67108863&be;N=0|N+(0|be/67108864),we=0|we+V,V=67108863&we,N=0|N+(we>>>26),b+=N>>>26,N&=67108863}B.words[C]=V,I=N,N=b}return I===0?B.length--:B.words[C]=I,B.strip()}function r(G,T,B){var I=new i;return I.mulp(G,T,B)}function i(G,T){this.x=G,this.y=T}function c(G,T){this.name=G,this.p=new n(T,16),this.n=this.p.bitLength(),this.k=new n(1).iushln(this.n).isub(this.p),this.tmp=this._tmp()}function h(){c.call(this,"k256","ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe fffffc2f")}function g(){c.call(this,"p224","ffffffff ffffffff ffffffff ffffffff 00000000 00000000 00000001")}function S(){c.call(this,"p192","ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff")}function k(){c.call(this,"25519","7fffffffffffffff ffffffffffffffff ffffffffffffffff ffffffffffffffed")}function M(G){if(typeof G=="string"){var T=n._prime(G);this.m=T.p,this.prime=T}else m(G.gtn(1),"modulus must be greater than 1"),this.m=G,this.prime=null}function E(G){M.call(this,G),this.shift=this.m.bitLength(),this.shift%26!=0&&(this.shift+=26-this.shift%26),this.r=new n(1).iushln(this.shift),this.r2=this.imod(this.r.sqr()),this.rinv=this.r._invmp(this.m),this.minv=this.rinv.mul(this.r).isubn(1).div(this.m),this.minv=this.minv.umod(this.r),this.minv=this.r.sub(this.minv)}typeof l=="object"?l.exports=n:y.BN=n,n.BN=n,n.wordSize=26;var x;try{x=typeof window!="undefined"&&typeof window.Buffer!="undefined"?window.Buffer:_("buffer").Buffer}catch{}n.isBN=function(T){return T instanceof n||T!==null&&typeof T=="object"&&T.constructor.wordSize===n.wordSize&&Array.isArray(T.words)},n.max=function(T,B){return 0<T.cmp(B)?T:B},n.min=function(T,B){return 0>T.cmp(B)?T:B},n.prototype._init=function(T,B,I){if(typeof T=="number")return this._initNumber(T,B,I);if(typeof T=="object")return this._initArray(T,B,I);B==="hex"&&(B=16),m(B===(0|B)&&2<=B&&36>=B),T=T.toString().replace(/\s+/g,"");var b=0;T[0]==="-"&&(b++,this.negative=1),b<T.length&&(B===16?this._parseHex(T,b,I):(this._parseBase(T,B,b),I==="le"&&this._initArray(this.toArray(),B,I)))},n.prototype._initNumber=function(T,B,I){0>T&&(this.negative=1,T=-T),67108864>T?(this.words=[67108863&T],this.length=1):4503599627370496>T?(this.words=[67108863&T,67108863&T/67108864],this.length=2):(m(9007199254740992>T),this.words=[67108863&T,67108863&T/67108864,1],this.length=3),I!=="le"||this._initArray(this.toArray(),B,I)},n.prototype._initArray=function(T,B,I){if(m(typeof T.length=="number"),0>=T.length)return this.words=[0],this.length=1,this;this.length=xe(T.length/3),this.words=Array(this.length);for(var b=0;b<this.length;b++)this.words[b]=0;var C=0,N,V;if(I==="be")for(b=T.length-1,N=0;0<=b;b-=3)V=T[b]|T[b-1]<<8|T[b-2]<<16,this.words[N]|=67108863&V<<C,this.words[N+1]=67108863&V>>>26-C,C+=24,26<=C&&(C-=26,N++);else if(I==="le")for(b=0,N=0;b<T.length;b+=3)V=T[b]|T[b+1]<<8|T[b+2]<<16,this.words[N]|=67108863&V<<C,this.words[N+1]=67108863&V>>>26-C,C+=24,26<=C&&(C-=26,N++);return this.strip()},n.prototype._parseHex=function(T,B,I){this.length=xe((T.length-B)/6),this.words=Array(this.length);for(var b=0;b<this.length;b++)this.words[b]=0;var C=0,N=0,V;if(I==="be")for(b=T.length-1;b>=B;b-=2)V=o(T,B,b)<<C,this.words[N]|=67108863&V,18<=C?(C-=18,N+=1,this.words[N]|=V>>>26):C+=8;else{var D=T.length-B;for(b=D%2==0?B+1:B;b<T.length;b+=2)V=o(T,B,b)<<C,this.words[N]|=67108863&V,18<=C?(C-=18,N+=1,this.words[N]|=V>>>26):C+=8}this.strip()},n.prototype._parseBase=function(T,B,I){this.words=[0],this.length=1;for(var b=0,C= Line truncated
we accept pull requests
https://github.com/crypto-browserify/crypto-browserify`)},R.constants={DH_CHECK_P_NOT_SAFE_PRIME:2,DH_CHECK_P_NOT_PRIME:1,DH_UNABLE_TO_CHECK_GENERATOR:4,DH_NOT_SUITABLE_GENERATOR:8,NPN_ENABLED:1,ALPN_ENABLED:1,RSA_PKCS1_PADDING:1,RSA_SSLV23_PADDING:2,RSA_NO_PADDING:3,RSA_PKCS1_OAEP_PADDING:4,RSA_X931_PADDING:5,RSA_PKCS1_PSS_PADDING:6,POINT_CONVERSION_COMPRESSED:2,POINT_CONVERSION_UNCOMPRESSED:4,POINT_CONVERSION_HYBRID:6}},{"browserify-cipher":60,"browserify-sign":67,"browserify-sign/algos":64,"create-ecdh":83,"create-hash":85,"create-hmac":87,"diffie-hellman":99,pbkdf2:186,"public-encrypt":194,randombytes:209,randomfill:210}],91:[function(_,K,R){(function(l){(function(){function y(){return!!(typeof window!="undefined"&&window.process&&(window.process.type==="renderer"||window.process.__nwjs))||!(typeof navigator!="undefined"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))&&(typeof document!="undefined"&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||typeof window!="undefined"&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||typeof navigator!="undefined"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&31<=parseInt(RegExp.$1,10)||typeof navigator!="undefined"&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))}function m(a){if(a[0]=(this.useColors?"%c":"")+this.namespace+(this.useColors?" %c":" ")+a[0]+(this.useColors?"%c ":" ")+"+"+K.exports.humanize(this.diff),!this.useColors)return;let f="color: "+this.color;a.splice(1,0,f,"color: inherit");let s=0,e=0;a[0].replace(/%[a-zA-Z%]/g,r=>{r==="%%"||(s++,r==="%c"&&(e=s))}),a.splice(e,0,f)}function p(a){try{a?R.storage.setItem("debug",a):R.storage.removeItem("debug")}catch{}}function n(){let a;try{a=R.storage.getItem("debug")}catch{}return!a&&typeof l!="undefined"&&"env"in l&&(a=l.env.DEBUG),a}function u(){try{return localStorage}catch{}}R.formatArgs=m,R.save=p,R.load=n,R.useColors=y,R.storage=u(),R.destroy=(()=>{let a=!1;return()=>{a||(a=!0,console.warn("Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."))}})(),R.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],R.log=console.debug||console.log||(()=>{}),K.exports=_("./common")(R);let{formatters:o}=K.exports;o.j=function(a){try{return JSON.stringify(a)}catch(f){return"[UnexpectedJSONParseError]: "+f.message}}}).call(this)}).call(this,_("_process"))},{"./common":92,_process:193}],92:[function(_,K,R){function l(y){function m(r){let i=0;for(let c=0;c<r.length;c++)i=(i<<5)-i+r.charCodeAt(c),i|=0;return p.colors[ut(i)%p.colors.length]}function p(r){function i(...k){if(!i.enabled)return;let M=i,E=+new Date,x=E-(h||E);M.diff=x,M.prev=h,M.curr=E,h=E,k[0]=p.coerce(k[0]),typeof k[0]!="string"&&k.unshift("%O");let U=0;k[0]=k[0].replace(/%([a-zA-Z%])/g,(X,ee)=>{if(X==="%%")return"%";U++;let ue=p.formatters[ee];if(typeof ue=="function"){let G=k[U];X=ue.call(M,G),k.splice(U,1),U--}return X}),p.formatArgs.call(M,k),(M.log||p.log).apply(M,k)}let c=null,h,g,S;return i.namespace=r,i.useColors=p.useColors(),i.color=p.selectColor(r),i.extend=n,i.destroy=p.destroy,Object.defineProperty(i,"enabled",{enumerable:!0,configurable:!1,get:()=>c===null?(g!==p.namespaces&&(g=p.namespaces,S=p.enabled(r)),S):c,set:k=>{c=k}}),typeof p.init=="function"&&p.init(i),i}function n(r,i){let c=p(this.namespace+(typeof i=="undefined"?":":i)+r);return c.log=this.log,c}function u(r){p.save(r),p.namespaces=r,p.names=[],p.skips=[];let i,c=(typeof r=="string"?r:"").split(/[\s,]+/),h=c.length;for(i=0;i<h;i++)c[i]&&(r=c[i].replace(/\*/g,".*?"),r[0]==="-"?p.skips.push(new RegExp("^"+r.slice(1)+"$")):p.names.push(new RegExp("^"+r+"$")))}function o(){let r=[...p.names.map(f),...p.skips.map(f).map(i=>"-"+i)].join(",");return p.enable(""),r}function a(r){if(r[r.length-1]==="*")return!0;let i,c;for(i=0,c=p.skips.length;i<c;i++)if(p.skips[i].test(r))return!1;for(i=0,c=p.names.length;i<c;i++)if(p.names[i].test(r))return!0;return!1}function f(r){return r.toString().substring(2,r.toString().length-2).replace(/\.\*\?$/,"*")}function s(r){return r instanceof Error?r.stack||r.messa Line truncated
Use Chrome, Firefox or Internet Explorer 11`)}function p(f,s){if(f>4294967295)throw new RangeError("requested too many random bytes");var e=o.allocUnsafe(f);if(0<f)if(65536<f)for(var r=0;r<f;r+=65536)a.getRandomValues(e.slice(r,r+65536));else a.getRandomValues(e);return typeof s=="function"?l.nextTick(function(){s(null,e)}):e}var n=65536,u=4294967295,o=_("safe-buffer").Buffer,a=y.crypto||y.msCrypto;K.exports=a&&a.getRandomValues?p:m}).call(this)}).call(this,_("_process"),typeof global=="undefined"?typeof self=="undefined"?typeof window=="undefined"?{}:window:self:global)},{_process:193,"safe-buffer":235}],210:[function(_,K,R){(function(l,y){(function(){"use strict";function m(){throw new Error(`secure random number generation not supported by this browser
use chrome, FireFox or Internet Explorer 11`)}function p(h,g){if(typeof h!="number"||h!==h)throw new TypeError("offset must be a number");if(4294967295<h||0>h)throw new TypeError("offset must be a uint32");if(h>r||h>g)throw new RangeError("offset out of range")}function n(h,g,S){if(typeof h!="number"||h!==h)throw new TypeError("size must be a number");if(4294967295<h||0>h)throw new TypeError("size must be a uint32");if(h+g>S||h>r)throw new RangeError("buffer too small")}function u(h,g,S,k){if(!e.isBuffer(h)&&!(h instanceof y.Uint8Array))throw new TypeError('"buf" argument must be a Buffer or Uint8Array');if(typeof g=="function")k=g,g=0,S=h.length;else if(typeof S=="function")k=S,S=h.length-g;else if(typeof k!="function")throw new TypeError('"cb" argument must be a function');return p(g,h.length),n(S,g,h.length),o(h,g,S,k)}function o(h,g,S,k){if(l.browser){var M=h.buffer,E=new Uint8Array(M,g,S);return i.getRandomValues(E),k?void l.nextTick(function(){k(null,h)}):h}if(k)return void s(S,function(U,j){return U?k(U):(j.copy(h,g),void k(null,h))});var x=s(S);return x.copy(h,g),h}function a(h,g,S){if(typeof g=="undefined"&&(g=0),!e.isBuffer(h)&&!(h instanceof y.Uint8Array))throw new TypeError('"buf" argument must be a Buffer or Uint8Array');return p(g,h.length),S===void 0&&(S=h.length-g),n(S,g,h.length),o(h,g,S)}var f=_("safe-buffer"),s=_("randombytes"),e=f.Buffer,r=f.kMaxLength,i=y.crypto||y.msCrypto,c=ct(2,32)-1;i&&i.getRandomValues||!l.browser?(R.randomFill=u,R.randomFillSync=a):(R.randomFill=m,R.randomFillSync=m)}).call(this)}).call(this,_("_process"),typeof global=="undefined"?typeof self=="undefined"?typeof window=="undefined"?{}:window:self:global)},{_process:193,randombytes:209,"safe-buffer":235}],211:[function(_,K,R){"use strict";function l(o,a,f){if(typeof a!="string")throw new TypeError("argument str must be a string");var s=a.indexOf("=");if(s===-1)return-2;var e=a.slice(s+1).split(","),r=[];r.type=a.slice(0,s);for(var i=0;i<e.length;i++){var c=e[i].split("-"),h=parseInt(c[0],10),g=parseInt(c[1],10);isNaN(h)?(h=o-g,g=o-1):isNaN(g)&&(g=o-1),g>o-1&&(g=o-1),!(isNaN(h)||isNaN(g)||h>g||0>h)&&r.push({start:h,end:g})}return 1>r.length?-1:f&&f.combine?y(r):r}function y(o){for(var a=o.map(m).sort(u),f=0,s=1;s<a.length;s++){var e=a[s],r=a[f];e.start>r.end+1?a[++f]=e:e.end>r.end&&(r.end=e.end,r.index=je(r.index,e.index))}a.length=f+1;var i=a.sort(n).map(p);return i.type=o.type,i}function m(o,a){return{start:o.start,end:o.end,index:a}}function p(o){return{start:o.start,end:o.end}}function n(o,a){return o.index-a.index}function u(o,a){return o.start-a.start}K.exports=l},{}],212:[function(_,K,R){let{Writable:l,PassThrough:y}=_("readable-stream");class m extends l{constructor(n,u={}){super(u),this.destroyed=!1,this._queue=[],this._position=n||0,this._cb=null,this._buffer=null,this._out=null}_write(n,u,o){let a=!0;for(;;){if(this.destroyed)return;if(this._queue.length===0)return this._buffer=n,void(this._cb=o);this._buffer=null;var f=this._queue[0];let s=Xe(f.start-this._position,0),e=f.end-this._position;if(s>=n.length)return this._position+=n.length,o(null);let r;if(e>n.length){this._position+=n.length,r=s===0?n:n.slice(s),a=f.stream.write(r)&&a;break}this._position+=e,r=s===0&&e===n.length?n:n.slice(s,e),a=f.stream.write(r)&&a,f.last&&f.stream.end(),n=n.slice(e),this._queue.shift()}a?o(null):f.stream.once("drain",o.bind(null,null))}slice(n){if(this.destroyed)return null;Array.isArray(n)||(n=[n]);let u=new y;return n.forEach((o,a)=>{this._queue.push({start:o.start,end:o.end,stream:u,last:a===n.length-1})}),this._buffer&&this._write(this._buffer,null,this._cb),u}destroy(n){this.destroyed||(this.destroyed=!0,n&&this.emit("error",n))}}K.exports=m},{"readable-stream":228}],213:[function(_,K,R){"use strict";function l(f){return parseInt(f,10)===f}function y(f){function s(){for(var i=Array(f),c=0;c<f;c++)i[c]=c;return i}function e(i){if(i===void 0){i=Array(f);for(var c=0;c<f;c++)i[c]=rt(Math.random()*f)}else if(typeof i=="string")i=""+i,i=i.split("").map(function(E){return E.charCodeAt(0)%f});else if(Array.isArray(i)){if(!i.every(function(E){return typeof E=="number"&&E===(0|E)}))throw new TypeError("invalid seed key specified: not array of integers")}else throw new TypeError("invalid seed key specified");for(var h=i.length,g=s(),S=0,k=0;k<f;k++){S=(S+g[k]+i[k%h])%f;var M=g[k];g[k]=g[S],g[S]=M}return g}function r(i){this.s=e(i),this.i=0,this.j=0}return r.prototype.randomNative=function(){this.i=(this.i+1)%f,this.j=(this.j+this.s[this.i])%f;var i=this.s[this.i];this.s[this.i]=this.s[this.j],this.s[this.j]=i;var c=this.s[(this.s[this.i]+this.s[this.j])%f];return c},r.prototype.randomUInt32=function(){var i=this.randomByte(),c=this.randomByte(),h=this.randomByte(),g=this.randomByte();return 256*(256*(256*i+c)+h)+g},r.prototype.randomFloat=function(){return this.randomUInt32()/4294967296},r.prototype.random=function(){var i,c;if(arguments.length===1)i=0,c=arguments[0];else if(arguments.length===2)i=arguments[0],c=arguments[1 Line truncated
`}),h=h+"("+p.toString().replace("ENTRY_MODULE",JSON.stringify(e))+")({"+c.main.map(function(E){return""+JSON.stringify(E)+": "+i.main[E].toString()}).join(",")+"})(self);";var g=new window.Blob([h],{type:"text/javascript"});if(r.bare)return g;var S=window.URL||window.webkitURL||window.mozURL||window.msURL,k=S.createObjectURL(g),M=new window.Worker(k);return M.objectURL=k,M}},function(l,y){l.exports=function(p,n,u){function o(f,s){f|=0,s|=0;var e=0,r=0,i=0,c=0,h=0,g=0,S=0,k=0,M=0,E=0,x=0,U=0,j=0,X=0;for(i=0|a[s+320>>2],h=0|a[s+324>>2],S=0|a[s+328>>2],M=0|a[s+332>>2],x=0|a[s+336>>2],e=0;(0|e)<(0|f);e=0|e+64){for(c=i,g=h,k=S,E=M,U=x,r=0;64>(0|r);r=0|r+4)X=0|a[e+r>>2],j=0|(0|(i<<5|i>>>27)+(h&S|~h&M))+(0|(0|X+x)+1518500249),x=M,M=S,S=h<<30|h>>>2,h=i,i=j,a[f+r>>2]=X;for(r=0|f+64;(0|r)<(0|f+80);r=0|r+4)X=(a[r-12>>2]^a[r-32>>2]^a[r-56>>2]^a[r-64>>2])<<1|(a[r-12>>2]^a[r-32>>2]^a[r-56>>2]^a[r-64>>2])>>>31,j=0|(0|(i<<5|i>>>27)+(h&S|~h&M))+(0|(0|X+x)+1518500249),x=M,M=S,S=h<<30|h>>>2,h=i,i=j,a[r>>2]=X;for(r=0|f+80;(0|r)<(0|f+160);r=0|r+4)X=(a[r-12>>2]^a[r-32>>2]^a[r-56>>2]^a[r-64>>2])<<1|(a[r-12>>2]^a[r-32>>2]^a[r-56>>2]^a[r-64>>2])>>>31,j=0|(0|(i<<5|i>>>27)+(h^S^M))+(0|(0|X+x)+1859775393),x=M,M=S,S=h<<30|h>>>2,h=i,i=j,a[r>>2]=X;for(r=0|f+160;(0|r)<(0|f+240);r=0|r+4)X=(a[r-12>>2]^a[r-32>>2]^a[r-56>>2]^a[r-64>>2])<<1|(a[r-12>>2]^a[r-32>>2]^a[r-56>>2]^a[r-64>>2])>>>31,j=0|(0|(i<<5|i>>>27)+(h&S|h&M|S&M))+(0|(0|X+x)-1894007588),x=M,M=S,S=h<<30|h>>>2,h=i,i=j,a[r>>2]=X;for(r=0|f+240;(0|r)<(0|f+320);r=0|r+4)X=(a[r-12>>2]^a[r-32>>2]^a[r-56>>2]^a[r-64>>2])<<1|(a[r-12>>2]^a[r-32>>2]^a[r-56>>2]^a[r-64>>2])>>>31,j=0|(0|(i<<5|i>>>27)+(h^S^M))+(0|(0|X+x)-899497514),x=M,M=S,S=h<<30|h>>>2,h=i,i=j,a[r>>2]=X;i=0|i+c,h=0|h+g,S=0|S+k,M=0|M+E,x=0|x+U}a[s+320>>2]=i,a[s+324>>2]=h,a[s+328>>2]=S,a[s+332>>2]=M,a[s+336>>2]=x}var a=new p.Int32Array(u);return{hash:o}}},function(l,y){var m=this,p=void 0;typeof self!="undefined"&&typeof self.FileReaderSync!="undefined"&&(p=new self.FileReaderSync);var n=function(a,f,s,e,r,i){var c=i%4,h=(r+c)%4,g=r-h,S;switch(c){case 0:f[i]=a.charCodeAt(e+3);case 1:f[0|i+1-(c<<1)]=a.charCodeAt(e+2);case 2:f[0|i+2-(c<<1)]=a.charCodeAt(e+1);case 3:f[0|i+3-(c<<1)]=a.charCodeAt(e)}if(!(r<h+(4-c))){for(S=4-c;S<g;S=0|S+4)s[i+S>>2]=a.charCodeAt(e+S)<<24|a.charCodeAt(e+S+1)<<16|a.charCodeAt(e+S+2)<<8|a.charCodeAt(e+S+3);switch(h){case 3:f[0|i+g+1]=a.charCodeAt(e+g+2);case 2:f[0|i+g+2]=a.charCodeAt(e+g+1);case 1:f[0|i+g+3]=a.charCodeAt(e+g)}}},u=function(a,f,s,e,r,i){var c=i%4,h=(r+c)%4,g=r-h,S;switch(c){case 0:f[i]=a[e+3];case 1:f[0|i+1-(c<<1)]=a[e+2];case 2:f[0|i+2-(c<<1)]=a[e+1];case 3:f[0|i+3-(c<<1)]=a[e]}if(!(r<h+(4-c))){for(S=4-c;S<g;S=0|S+4)s[0|i+S>>2]=a[e+S]<<24|a[e+S+1]<<16|a[e+S+2]<<8|a[e+S+3];switch(h){case 3:f[0|i+g+1]=a[e+g+2];case 2:f[0|i+g+2]=a[e+g+1];case 1:f[0|i+g+3]=a[e+g]}}},o=function(a,f,s,e,r,i){var c=void 0,h=i%4,g=(r+h)%4,S=r-g,k=new Uint8Array(p.readAsArrayBuffer(a.slice(e,e+r)));switch(h){case 0:f[i]=k[3];case 1:f[0|i+1-(h<<1)]=k[2];case 2:f[0|i+2-(h<<1)]=k[1];case 3:f[0|i+3-(h<<1)]=k[0]}if(!(r<g+(4-h))){for(c=4-h;c<S;c=0|c+4)s[0|i+c>>2]=k[c]<<24|k[c+1]<<16|k[c+2]<<8|k[c+3];switch(g){case 3:f[0|i+S+1]=k[S+2];case 2:f[0|i+S+2]=k[S+1];case 1:f[0|i+S+3]=k[S]}}};l.exports=function(a,f,s,e,r,i){if(typeof a=="string")return n(a,f,s,e,r,i);if(a instanceof Array||m&&m.Buffer&&m.Buffer.isBuffer(a))return u(a,f,s,e,r,i);if(a instanceof ArrayBuffer)return u(new Uint8Array(a),f,s,e,r,i);if(a.buffer instanceof ArrayBuffer)return u(new Uint8Array(a.buffer,a.byteOffset,a.byteLength),f,s,e,r,i);if(a instanceof Blob)return o(a,f,s,e,r,i);throw new Error("Unsupported data type.")}},function(l,y,m){function p(s,e){if(!(s instanceof e))throw new TypeError("Cannot call a class as a function")}var n=(function(){function s(e,r){for(var i=0,c;i<r.length;i++)c=r[i],c.enumerable=c.enumerable||!1,c.configurable=!0,"value"in c&&(c.writable=!0),Object.defineProperty(e,c.key,c)}return function(e,r,i){return r&&s(e.prototype,r),i&&s(e,i),e}})(),u=m(0),o=m(1),a=o.toHex,f=(function(){function s(){p(this,s),this._rusha=new u,this._rusha.resetState()}return s.prototype.update=function(r){return this._rusha.append(r),this},s.prototype.digest=function(r){var i=this._rusha.rawEnd().buffer;if(!r)return i;if(r==="hex")return a(i);throw new Error("unsupported digest encoding")},n(s,[{key:"state",get:function(){return this._rusha.getState()},set:function(e){this._rusha.setState(e)}}]),s})();l.exports=function(){return new f}}])})},{}],235:[function(_,K,R){function l(n,u){for(var o in n)u[o]=n[o]}function y(n,u,o){return p(n,u,o)}var m=_("buffer"),p=m.Buffer;p.from&&p.alloc&&p.allocUnsafe&&p.allocUnsafeSlow?K.exports=m:(l(m,R),R.Buffer=y),y.prototype=Object.create(p.prototype),l(p,y),y.from=function(n,u,o){if(typeof n=="number")throw new TypeError("Argument must not be a number");return p(n,u,o)},y.alloc=function(n,u,o){if(typeof n!="number")throw new TypeError("Argument must be a number");var a=p(n);return u===void 0?a.fill(0):typeof o==" Line truncated
`," "],r=["{","}","|","\\","^","`"].concat(e),i=["'"].concat(r),c=["%","/","?",";","#"].concat(i),h=["/","?","#"],g=255,S=/^[+a-z0-9A-Z_-]{0,63}$/,k=/^([+a-z0-9A-Z_-]{0,63})(.*)$/,M={javascript:!0,"javascript:":!0},E={javascript:!0,"javascript:":!0},x={http:!0,https:!0,ftp:!0,gopher:!0,file:!0,"http:":!0,"https:":!0,"ftp:":!0,"gopher:":!0,"file:":!0},U=_("querystring");l.prototype.parse=function(j,X,ee){if(!o.isString(j))throw new TypeError("Parameter 'url' must be a string, not "+typeof j);var ue=j.indexOf("?"),G=ue!==-1&&ue<j.indexOf("#")?"?":"#",T=j.split(G),B=/\\/g;T[0]=T[0].replace(B,"/"),j=T.join(G);var I=j;if(I=I.trim(),!ee&&j.split("#").length===1){var b=s.exec(I);if(b)return this.path=I,this.href=I,this.pathname=b[1],b[2]?(this.search=b[2],this.query=X?U.parse(this.search.substr(1)):this.search.substr(1)):X&&(this.search="",this.query={}),this}var C=a.exec(I);if(C){C=C[0];var N=C.toLowerCase();this.protocol=N,I=I.substr(C.length)}if(ee||C||I.match(/^\/\/[^@\/]+@[^@\/]+/)){var V=I.substr(0,2)==="//";V&&!(C&&E[C])&&(I=I.substr(2),this.slashes=!0)}if(!E[C]&&(V||C&&!x[C])){for(var D=-1,Y=0,te;Y<h.length;Y++)te=I.indexOf(h[Y]),te!==-1&&(D===-1||te<D)&&(D=te);var pe,le;le=D===-1?I.lastIndexOf("@"):I.lastIndexOf("@",D),le!==-1&&(pe=I.slice(0,le),I=I.slice(le+1),this.auth=decodeURIComponent(pe)),D=-1;for(var Y=0,te;Y<c.length;Y++)te=I.indexOf(c[Y]),te!==-1&&(D===-1||te<D)&&(D=te);D===-1&&(D=I.length),this.host=I.slice(0,D),I=I.slice(D),this.parseHost(),this.hostname=this.hostname||"";var be=this.hostname[0]==="["&&this.hostname[this.hostname.length-1]==="]";if(!be){for(var we=this.hostname.split(/\./),Y=0,Be=we.length,Ze;Y<Be;Y++)if(Ze=we[Y],Ze&&!Ze.match(S)){for(var gt="",st=0,_e=Ze.length;st<_e;st++)gt+=127<Ze.charCodeAt(st)?"x":Ze[st];if(!gt.match(S)){var Le=we.slice(0,Y),ze=we.slice(Y+1),ft=Ze.match(k);ft&&(Le.push(ft[1]),ze.unshift(ft[2])),ze.length&&(I="/"+ze.join(".")+I),this.hostname=Le.join(".");break}}}this.hostname=255<this.hostname.length?"":this.hostname.toLowerCase(),be||(this.hostname=u.toASCII(this.hostname));var Dt=this.port?":"+this.port:"",q=this.hostname||"";this.host=q+Dt,this.href+=this.host,be&&(this.hostname=this.hostname.substr(1,this.hostname.length-2),I[0]!=="/"&&(I="/"+I))}if(!M[N]){for(var Y=0,Be=i.length,P;Y<Be;Y++)if(P=i[Y],I.indexOf(P)!==-1){var F=encodeURIComponent(P);F===P&&(F=escape(P)),I=I.split(P).join(F)}}var J=I.indexOf("#");J!==-1&&(this.hash=I.substr(J),I=I.slice(0,J));var oe=I.indexOf("?");if(oe===-1?X&&(this.search="",this.query={}):(this.search=I.substr(oe),this.query=I.substr(oe+1),X&&(this.query=U.parse(this.query)),I=I.slice(0,oe)),I&&(this.pathname=I),x[N]&&this.hostname&&!this.pathname&&(this.pathname="/"),this.pathname||this.search){var Dt=this.pathname||"",ve=this.search||"";this.path=Dt+ve}return this.href=this.format(),this},l.prototype.format=function(){var j=this.auth||"";j&&(j=encodeURIComponent(j),j=j.replace(/%3A/i,":"),j+="@");var X=this.protocol||"",ee=this.pathname||"",ue=this.hash||"",G=!1,T="";this.host?G=j+this.host:this.hostname&&(G=j+(this.hostname.indexOf(":")===-1?this.hostname:"["+this.hostname+"]"),this.port&&(G+=":"+this.port)),this.query&&o.isObject(this.query)&&Object.keys(this.query).length&&(T=U.stringify(this.query));var B=this.search||T&&"?"+T||"";return X&&X.substr(-1)!==":"&&(X+=":"),this.slashes||(!X||x[X])&&G!==!1?(G="//"+(G||""),ee&&ee.charAt(0)!=="/"&&(ee="/"+ee)):!G&&(G=""),ue&&ue.charAt(0)!=="#"&&(ue="#"+ue),B&&B.charAt(0)!=="?"&&(B="?"+B),ee=ee.replace(/[?#]/g,function(I){return encodeURIComponent(I)}),B=B.replace("#","%23"),X+G+ee+B+ue},l.prototype.resolve=function(j){return this.resolveObject(y(j,!1,!0)).format()},l.prototype.resolveObject=function(j){if(o.isString(j)){var X=new l;X.parse(j,!1,!0),j=X}for(var ee=new l,ue=Object.keys(this),G=0,T;G<ue.length;G++)T=ue[G],ee[T]=this[T];if(ee.hash=j.hash,j.href==="")return ee.href=ee.format(),ee;if(j.slashes&&!j.protocol){for(var B=Object.keys(j),I=0,b;I<B.length;I++)b=B[I],b!=="protocol"&&(ee[b]=j[b]);return x[ee.protocol]&&ee.hostname&&!ee.pathname&&(ee.path=ee.pathname="/"),ee.href=ee.format(),ee}if(j.protocol&&j.protocol!==ee.protocol){if(!x[j.protocol]){for(var C=Object.keys(j),N=0,V;N<C.length;N++)V=C[N],ee[V]=j[V];return ee.href=ee.format(),ee}if(ee.protocol=j.protocol,!j.host&&!E[j.protocol]){for(var Be=(j.pathname||"").split("/");Be.length&&!(j.host=Be.shift()););j.host||(j.host=""),j.hostname||(j.hostname=""),Be[0]!==""&&Be.unshift(""),2>Be.length&&Be.unshift(""),ee.pathname=Be.join("/")}else ee.pathname=j.pathname;if(ee.search=j.search,ee.query=j.query,ee.host=j.host||"",ee.auth=j.auth,ee.hostname=j.hostname||j.host,ee.port=j.port,ee.pathname||ee.search){var D=ee.pathname||"",Y=ee.search||"";ee.path=D+Y}return ee.slashes=ee.slashes||j.slashes,ee.href=ee.format(),ee}var te=ee.pathname&&ee.pathname.charAt(0)==="/",pe=j.host||j.pathname&&j.pathname.charAt(0)==="/",le=pe||te||ee.host&&j.pathname,be=le,we=ee.pathname&&ee.pathname.split("/")||[],Be=j.pathname&&j.pathna Line truncated
Valid base64 characters are A-Z, a-z, 0-9, `+", "/`,and "="
`+"Expect errors in decoding."),Ce=Ce.replace(/[^A-Za-z0-9\+\/\=]/g,"");do Xe=this.KEY_STR.indexOf(Ce.charAt(_++)),xe=this.KEY_STR.indexOf(Ce.charAt(_++)),je=this.KEY_STR.indexOf(Ce.charAt(_++)),_t=this.KEY_STR.indexOf(Ce.charAt(_++)),$=Xe<<2|xe>>4,Ye=(xe&15)<<4|je>>2,Re=(je&3)<<6|_t,K.push($),je!==64&&K.push(Ye),_t!==64&&K.push(Re),$=Ye=Re="",Xe=xe=je=_t="";while(_<Ce.length);return K},fe.restore(qe,Te)},ct}]);var rh=eo(Qf(),1),to=eo(th(),1),cf=typeof window!="undefined"?window:globalThis,Eu=to.default&&to.default.default?to.default.default:to.default;cf.angular=nh.default;cf.moment=rh.default;cf.WebTorrent=Eu;})();
/*! Bundled license information:
angular/angular.js:
angular-route/angular-route.js:
angular-sanitize/angular-sanitize.js:
(**
* @license AngularJS v1.8.3
* (c) 2010-2020 Google LLC. http://angularjs.org
* License: MIT
*)
moment/moment.js:
(*! moment.js *)
(*! version : 2.30.1 *)
(*! authors : Tim Wood, Iskren Chernev, Moment.js contributors *)
(*! license : MIT *)
(*! momentjs.com *)
webtorrent/webtorrent.min.js:
(*! bittorrent-protocol. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> *)
(*! blob-to-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*)
(*! cache-chunk-store. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*! create-torrent. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> *)
(*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*! immediate-chunk-store. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*)
(*! lt_donthave. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> *)
(*! parse-torrent. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> *)
(*! https://mths.be/punycode v1.4.1 by @mathias *)
(*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*!
* range-parser
* Copyright(c) 2012-2014 TJ Holowaychuk
* Copyright(c) 2015-2016 Douglas Christopher Wilson
* MIT Licensed
*)
(*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*! simple-concat. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*! simple-peer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*! simple-websocket. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*! stream-to-blob. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*! stream-with-known-length-to-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> *)
(*! torrent-discovery. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> *)
(*! torrent-piece. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> *)
(*! ut_metadata. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> *)
(*! webtorrent. MIT License. WebTorrent LLC <https://webtorrent.io/opensource> *)
*/
+47 -13
View File
@@ -1,17 +1,51 @@
import angular from "angular";
import "angular-route";
import "angular-sanitize";
import "ng-file-upload/dist/ng-file-upload.js";
import moment from "moment";
import WebTorrent from "webtorrent/webtorrent.min.js";
import { createBeaconApp } from "../app.js";
// Ensure Angular modules register on the shared angular instance.
const globalScope = typeof window !== "undefined" ? window : globalThis;
function resolveWebTorrent() {
const globalScope =
(typeof window !== "undefined" && window) ||
(typeof globalThis !== "undefined" && globalThis) ||
null;
const webTorrentInstance = WebTorrent && WebTorrent.default ? WebTorrent.default : WebTorrent;
if (globalScope && typeof globalScope.WebTorrent === "function") {
return globalScope.WebTorrent;
}
globalScope.angular = angular;
globalScope.moment = moment;
globalScope.WebTorrent = webTorrentInstance;
throw new Error("WebTorrent runtime is not available on the global scope");
}
export { angular, moment, WebTorrent };
let appInstance = null;
function mountBeaconApp() {
if (appInstance) {
return appInstance;
}
if (typeof document === "undefined") {
throw new Error("Beacon runtime requires a document environment");
}
const WebTorrentCtor = resolveWebTorrent();
appInstance = createBeaconApp({ documentRef: document, WebTorrentCtor });
appInstance.mount();
return appInstance;
}
if (typeof document !== "undefined") {
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => {
try {
mountBeaconApp();
} catch (error) {
console.error("[beacon] Failed to mount app", error);
}
});
} else {
try {
mountBeaconApp();
} catch (error) {
console.error("[beacon] Failed to mount app", error);
}
}
}
export { createBeaconApp, mountBeaconApp };
+2 -6
View File
@@ -187,10 +187,6 @@ export function createToastManager(documentRef, timeoutRef = setTimeout, clearTi
};
}
export function registerBeaconToast(app) {
app.factory("beaconToast", ["$document", "$timeout", function ($document, $timeout) {
const doc = $document[0];
const manager = createToastManager(doc, $timeout, $timeout.cancel);
return manager;
}]);
export function createBeaconToast(documentRef, timeoutRef = setTimeout, clearTimeoutRef = clearTimeout) {
return createToastManager(documentRef, timeoutRef, clearTimeoutRef);
}
+211 -92
View File
@@ -10,34 +10,35 @@ const COLUMN_DEFS = [
label: "Progress",
headerClass: "w-24 text-right",
cellClass: "tabular-nums text-right",
filter: { name: "progress" },
formatter: "progress",
},
{
key: "downloadSpeed",
label: "\u2193 Speed",
headerClass: "w-24 text-right",
cellClass: "tabular-nums text-right",
filter: { name: "pbytes", args: [1] },
formatter: "bytesPerSecond",
},
{
key: "uploadSpeed",
label: "\u2191 Speed",
headerClass: "w-24 text-right",
cellClass: "tabular-nums text-right",
filter: { name: "pbytes", args: [1] },
formatter: "bytesPerSecond",
},
{
key: "numPeers",
label: "Peers",
headerClass: "w-20 text-right",
cellClass: "tabular-nums text-right",
formatter: "integer",
},
{
key: "ratio",
label: "Ratio",
headerClass: "w-20 text-right",
cellClass: "tabular-nums text-right",
filter: { name: "number", args: [2] },
formatter: "ratio",
},
];
@@ -46,102 +47,220 @@ function getRowId(torrent) {
return "";
}
return torrent.infoHash || torrent.magnetURI || torrent.name || Math.random();
return torrent.infoHash || torrent.magnetURI || torrent.name || String(Math.random());
}
export function registerTorrentTable(app) {
app.component("torrentTable", {
bindings: {
torrents: "<",
selected: "<?",
onSelect: "&?",
},
controller: [
"$filter",
function ($filter) {
this.$onChanges = function () {
this.rows = Array.isArray(this.torrents) ? this.torrents : [];
};
function isSelectedTorrent(selected, torrent) {
if (!selected || !torrent) {
return false;
}
this.isSelected = function (torrent) {
if (!this.selected || !torrent) {
return false;
}
return (
selected === torrent ||
(selected.magnetURI && selected.magnetURI === torrent.magnetURI) ||
(selected.infoHash && selected.infoHash === torrent.infoHash)
);
}
return (
this.selected === torrent ||
(this.selected.magnetURI && this.selected.magnetURI === torrent.magnetURI) ||
(this.selected.infoHash && this.selected.infoHash === torrent.infoHash)
);
};
function formatProgress(value) {
if (typeof value !== "number" || Number.isNaN(value)) {
return "";
}
this.selectTorrent = function (torrent) {
if (typeof this.onSelect === "function") {
this.onSelect({ torrent });
}
};
return `${(value * 100).toFixed(1)}%`;
}
this.getRowKey = function (torrent) {
return getRowId(torrent);
};
function formatRatio(value) {
if (typeof value !== "number" || !Number.isFinite(value)) {
return "0.00";
}
this.getDisplayValue = function (torrent, column) {
const value = torrent ? torrent[column.key] : undefined;
return value.toFixed(2);
}
if (!column.filter || !$filter) {
return value;
}
function formatInteger(value) {
if (typeof value !== "number" || !Number.isFinite(value)) {
return "0";
}
const filterFn = $filter(column.filter.name);
const args = Array.isArray(column.filter.args) ? column.filter.args : [];
return filterFn(value, ...args);
};
},
],
template: `
<div class="overflow-hidden rounded-xl border border-border-translucent bg-surface shadow-sm">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-border-translucent text-sm">
<thead class="bg-surface-alt text-muted-strong">
<tr>
<th ng-repeat="column in $ctrl.columns"
scope="col"
class="px-4 py-3 font-semibold uppercase tracking-wide text-xs"
ng-class="column.headerClass">
{{ column.label }}
</th>
</tr>
</thead>
<tbody class="divide-y divide-border-translucent" ng-if="$ctrl.rows.length">
<tr ng-repeat="torrent in $ctrl.rows track by $ctrl.getRowKey(torrent)"
ng-click="$ctrl.selectTorrent(torrent)"
ng-keydown="($event.key === 'Enter' || $event.key === ' ') && ($event.preventDefault(), $ctrl.selectTorrent(torrent))"
ng-class="{ 'bg-info/10 text-text': $ctrl.isSelected(torrent) }"
class="group align-middle cursor-pointer transition hover:bg-panel-hover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-info"
role="button"
tabindex="0"
aria-pressed="$ctrl.isSelected(torrent)">
<td ng-repeat="column in $ctrl.columns"
class="px-4 py-3"
ng-class="column.cellClass">
<span>{{ $ctrl.getDisplayValue(torrent, column) }}</span>
</td>
</tr>
</tbody>
<tbody ng-if="!$ctrl.rows.length">
<tr>
<td class="px-4 py-8 text-center text-sm text-muted" colspan="{{$ctrl.columns.length}}">
No active torrents yet. Add a magnet link to get started.
</td>
</tr>
</tbody>
</table>
</div>
</div>
`,
$onInit() {
this.columns = COLUMN_DEFS;
this.rows = Array.isArray(this.torrents) ? this.torrents : [];
},
return Math.max(0, Math.floor(value)).toString();
}
function formatBytesPerSecond(value, formatter) {
if (typeof formatter === "function") {
return formatter(value, true) || "";
}
if (typeof value !== "number" || Number.isNaN(value) || value < 1) {
return "";
}
const units = ["B", "kB", "MB", "GB", "TB"];
const exponent = Math.min(Math.floor(Math.log(value) / Math.log(1000)), units.length - 1);
const val = (value / Math.pow(1000, exponent)).toFixed(1);
return `${val} ${units[exponent]}/s`;
}
function resolveFormatter(column, customFormatters) {
const name = column.formatter;
if (typeof name === "function") {
return name;
}
const userFormatter = customFormatters?.[name];
if (typeof userFormatter === "function") {
return userFormatter;
}
switch (name) {
case "progress":
return formatProgress;
case "ratio":
return formatRatio;
case "integer":
return formatInteger;
case "bytesPerSecond":
return (value) => formatBytesPerSecond(value, customFormatters?.bytes);
default:
return (value) => value;
}
}
export function createTorrentTable({
documentRef = typeof document !== "undefined" ? document : null,
root,
onSelect,
formatters = {},
} = {}) {
if (!documentRef) {
throw new Error("createTorrentTable requires a document reference");
}
if (!(root instanceof documentRef.defaultView.HTMLElement)) {
throw new Error("createTorrentTable requires a valid root element");
}
const doc = documentRef;
root.innerHTML = "";
const container = doc.createElement("div");
container.className = "overflow-hidden rounded-xl border border-border-translucent bg-surface shadow-sm";
const scroll = doc.createElement("div");
scroll.className = "overflow-x-auto";
container.appendChild(scroll);
const table = doc.createElement("table");
table.className = "min-w-full divide-y divide-border-translucent text-sm";
scroll.appendChild(table);
const thead = doc.createElement("thead");
thead.className = "bg-surface-alt text-muted-strong";
const headerRow = doc.createElement("tr");
COLUMN_DEFS.forEach((column) => {
const th = doc.createElement("th");
th.setAttribute("scope", "col");
th.className = "px-4 py-3 text-left text-xs font-semibold uppercase tracking-wide";
if (column.headerClass) {
th.className += ` ${column.headerClass}`;
}
th.textContent = column.label;
headerRow.appendChild(th);
});
thead.appendChild(headerRow);
table.appendChild(thead);
const tbody = doc.createElement("tbody");
tbody.className = "divide-y divide-border-translucent";
table.appendChild(tbody);
const emptyBody = doc.createElement("tbody");
const emptyRow = doc.createElement("tr");
const emptyCell = doc.createElement("td");
emptyCell.className = "px-4 py-8 text-center text-sm text-muted";
emptyCell.colSpan = COLUMN_DEFS.length;
emptyCell.textContent = "No active torrents yet. Add a magnet link to get started.";
emptyRow.appendChild(emptyCell);
emptyBody.appendChild(emptyRow);
table.appendChild(emptyBody);
root.appendChild(container);
function render(torrents = [], selectedTorrent = null) {
const rows = Array.isArray(torrents) ? torrents : [];
tbody.innerHTML = "";
if (!rows.length) {
tbody.hidden = true;
emptyBody.hidden = false;
return;
}
tbody.hidden = false;
emptyBody.hidden = true;
for (const torrent of rows) {
const row = doc.createElement("tr");
row.className = [
"group",
"align-middle",
"cursor-pointer",
"transition",
"hover:bg-panel-hover",
"focus-visible:outline",
"focus-visible:outline-2",
"focus-visible:outline-offset-2",
"focus-visible:outline-info",
].join(" ");
row.setAttribute("role", "button");
row.setAttribute("tabindex", "0");
row.dataset.torrentId = getRowId(torrent);
if (isSelectedTorrent(selectedTorrent, torrent)) {
row.classList.add("bg-info/10", "text-text");
row.setAttribute("aria-pressed", "true");
} else {
row.setAttribute("aria-pressed", "false");
}
row.addEventListener("click", () => {
if (typeof onSelect === "function") {
onSelect(torrent);
}
});
row.addEventListener("keydown", (event) => {
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
if (typeof onSelect === "function") {
onSelect(torrent);
}
}
});
COLUMN_DEFS.forEach((column) => {
const td = doc.createElement("td");
td.className = "px-4 py-3";
if (column.cellClass) {
td.className += ` ${column.cellClass}`;
}
const value = torrent ? torrent[column.key] : undefined;
const formatter = resolveFormatter(column, formatters);
const displayValue = formatter(value, torrent, column);
const span = doc.createElement("span");
span.textContent = displayValue == null ? "" : String(displayValue);
td.appendChild(span);
row.appendChild(td);
});
tbody.appendChild(row);
}
}
function destroy() {
root.innerHTML = "";
}
return { render, destroy };
}
-290
View File
@@ -1,290 +0,0 @@
<!-- MAIN CONTENT AREA -->
<div class="mx-auto max-w-5xl px-4 py-6 sm:px-6 lg:px-8 bv-stack">
<!-- Input row for adding or opening torrents -->
<section class="card p-6">
<form
class="bv-stack bv-stack--tight md:flex md:flex-row md:items-end md:gap-md"
ng-submit="addMagnet()"
>
<div class="bv-stack bv-stack--tight flex-1">
<label
class="text-xs font-semibold uppercase tracking-wide text-muted-strong"
for="torrentInput"
>
Magnet, hash, or HTTPS .torrent URL
</label>
<input
id="torrentInput"
class="input"
type="text"
placeholder="magnet:?xt=…"
ng-model="torrentInput"
ng-disabled="$root.disabled"
/>
</div>
<div class="flex flex-wrap items-center gap-3 md:justify-end">
<button
type="submit"
class="btn inline-flex items-center gap-2"
ng-disabled="!torrentInput.length || $root.disabled"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M12 3v14"></path>
<path d="m6 11 6 6 6-6"></path>
<path d="M19 21H5"></path>
</svg>
Download
</button>
<button
type="button"
class="btn-ghost inline-flex items-center gap-2"
ngf-select="$root.seedFiles($files)"
multiple="true"
ng-disabled="$root.disabled"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M12 21V7"></path>
<path d="m6 13 6-6 6 6"></path>
<path d="M5 21h14"></path>
</svg>
Seed files
</button>
</div>
</form>
</section>
<!-- Active torrent table using Tailwind tokens -->
<section class="card overflow-hidden" aria-label="Active torrents">
<torrent-table
torrents="torrentRows"
selected="$root.selectedTorrent"
on-select="selectTorrent(torrent)"
></torrent-table>
</section>
<!-- Selected torrent details: Pause/Resume, Download, Remove -->
<section class="card p-6" ng-if="selectedTorrent">
<div class="grid gap-xl lg:grid-cols-2">
<div class="bv-stack bv-stack--tight overflow-auto">
<div class="bv-stack bv-stack--tight">
<h2 class="text-lg font-semibold text-text">
{{ selectedTorrent.name }}
</h2>
<div class="flex flex-wrap gap-2">
<button
type="button"
class="btn-ghost inline-flex items-center gap-2"
ng-if="!selectedTorrent.paused"
ng-click="selectedTorrent.pause()"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<rect x="6" y="4" width="4" height="16"></rect>
<rect x="14" y="4" width="4" height="16"></rect>
</svg>
Pause
</button>
<button
type="button"
class="btn-ghost inline-flex items-center gap-2"
ng-if="selectedTorrent.paused"
ng-click="selectedTorrent.resume()"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<polygon points="6 4 20 12 6 20 6 4"></polygon>
</svg>
Resume
</button>
<button
type="button"
class="btn inline-flex items-center gap-2"
ng-click="$root.downloadAll(selectedTorrent)"
ng-disabled="selectedTorrent.progress < 1"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M12 3v14"></path>
<path d="m6 11 6 6 6-6"></path>
</svg>
Download all
</button>
<button
type="button"
class="btn-ghost inline-flex items-center gap-2"
data-variant="critical"
ng-click="selectedTorrent.destroy($root.destroyedTorrent)"
>
<svg
class="h-4 w-4"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M18 6L6 18"></path>
<path d="M6 6l12 12"></path>
</svg>
Remove
</button>
</div>
</div>
<div class="bv-stack bv-stack--tight">
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted">
Share
</h3>
<ul class="bv-stack bv-stack--tight text-sm text-muted-strong">
<li>
<button
type="button"
class="btn-ghost inline-flex items-center gap-2 text-xs"
ng-click="$root.copyMagnetURI(selectedTorrent)"
>
Copy magnet
</button>
</li>
<li>
<strong class="font-semibold text-text">Hash:</strong>
{{ selectedTorrent.infoHash }}
</li>
</ul>
</div>
</div>
<div class="bv-stack bv-stack--tight">
<h3 class="text-sm font-semibold uppercase tracking-wide text-muted">
Files
</h3>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-border-translucent text-sm">
<thead class="bg-surface-alt text-muted-strong">
<tr>
<th class="px-3 py-2 text-left font-medium">Name</th>
<th class="px-3 py-2 text-left font-medium">Size</th>
<th class="px-3 py-2 text-left font-medium">Priority</th>
</tr>
</thead>
<tbody class="divide-y divide-border-translucent bg-surface">
<tr class="align-top" ng-repeat="file in selectedTorrent.files">
<td class="px-3 py-2">
<span ng-hide="file.done">{{ file.name }}</span>
<a
class="text-info hover:text-info-strong"
ng-show="file.done"
ng-href="{{ file.url }}"
download="{{ file.name }}"
>
{{ file.name }}
</a>
</td>
<td class="px-3 py-2 text-muted-strong">
{{ file.length | pbytes }}
</td>
<td class="px-3 py-2">
<select
class="select"
name="{{ file.name }}Priority"
ng-model="file.priority"
ng-init="file.priority = '0'"
ng-change="$root.changePriority(file)"
aria-label="Set priority for {{ file.name }}"
>
<option value="1">High priority</option>
<option value="0" selected="">Low priority</option>
<option value="-1">Don't download</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</section>
<div class="text-center text-sm font-semibold text-muted">
Client stats: ↓ {{ client.downloadSpeed | pbytes }}/s · ↑ {{
client.uploadSpeed | pbytes }}/s · Ratio: {{ client.ratio | number:2 }}
</div>
</div>
<!-- Processing Spinner -->
<div
class="fixed inset-0 z-[60] flex items-center justify-center bg-overlay-muted/70 backdrop-blur-md"
ng-show="$root.processing"
>
<svg
class="h-12 w-12 animate-spin text-info-strong"
viewBox="0 0 24 24"
role="img"
aria-hidden="true"
>
<circle
class="stroke-border-translucent opacity-40"
cx="12"
cy="12"
r="9"
fill="none"
stroke-width="2"
></circle>
<path
class="stroke-current"
d="M21 12a9 9 0 0 0-9-9"
fill="none"
stroke-width="2"
stroke-linecap="round"
></path>
</svg>
</div>