- App.tsx: full navigation (Auth stack + Main tabs with 5 screens) - Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen - HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors - MapScreen: interactive map with layer toggles (6 layers) - MarketplaceScreen: categories (6), products (5), search - ChatScreen: AI chat with quick prompts (4), bot responses - ProfileScreen: user info, stats, menu (9 items), logout - AlertsScreen: alert list with severity, acknowledge - SensorsScreen: sensor list with type filters (6 types), search - ZonesScreen: zone cards with stats - SettingsScreen: language picker (FR/EN/ES/DE), privacy, about - Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n - Hooks: useSensors, useAlerts, useNotifications, useLocation - Components: Card, Button, LoadingSpinner, ErrorBoundary, Header - Services: iotService, notificationService (with axios API client) - Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN) - Theme: colors.ts with full design system (Blue Ocean palette) - Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
54 lines
2.2 KiB
JavaScript
54 lines
2.2 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.downloadImage = exports.downloadOrUseCachedImage = void 0;
|
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
// @ts-ignore
|
|
const jimp_compact_1 = __importDefault(require("jimp-compact"));
|
|
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
const path_1 = __importDefault(require("path"));
|
|
const stream_1 = __importDefault(require("stream"));
|
|
const tempy_1 = __importDefault(require("tempy"));
|
|
const util_1 = __importDefault(require("util"));
|
|
// cache downloaded images into memory
|
|
const cacheDownloadedKeys = {};
|
|
function stripQueryParams(url) {
|
|
return url.split('?')[0].split('#')[0];
|
|
}
|
|
async function downloadOrUseCachedImage(url) {
|
|
if (url in cacheDownloadedKeys) {
|
|
return cacheDownloadedKeys[url];
|
|
}
|
|
if (url.startsWith('http')) {
|
|
cacheDownloadedKeys[url] = await downloadImage(url);
|
|
}
|
|
else {
|
|
cacheDownloadedKeys[url] = url;
|
|
}
|
|
return cacheDownloadedKeys[url];
|
|
}
|
|
exports.downloadOrUseCachedImage = downloadOrUseCachedImage;
|
|
async function downloadImage(url) {
|
|
const outputPath = tempy_1.default.directory();
|
|
const response = await (0, node_fetch_1.default)(url);
|
|
if (!response.ok) {
|
|
throw new Error(`It was not possible to download image from '${url}'`);
|
|
}
|
|
// Download to local file
|
|
const streamPipeline = util_1.default.promisify(stream_1.default.pipeline);
|
|
const localPath = path_1.default.join(outputPath, path_1.default.basename(stripQueryParams(url)));
|
|
await streamPipeline(response.body, fs_extra_1.default.createWriteStream(localPath));
|
|
// If an image URL doesn't have a name, get the mime type and move the file.
|
|
const img = await jimp_compact_1.default.read(localPath);
|
|
const mime = img.getMIME().split('/').pop();
|
|
if (!localPath.endsWith(mime)) {
|
|
const newPath = path_1.default.join(outputPath, `image.${mime}`);
|
|
await fs_extra_1.default.move(localPath, newPath);
|
|
return newPath;
|
|
}
|
|
return localPath;
|
|
}
|
|
exports.downloadImage = downloadImage;
|
|
//# sourceMappingURL=Download.js.map
|