Files
Eric FELIXINE e30ae8ed09 feat(smart-app): implement complete mobile app MVP
- 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
2026-06-01 18:00:35 -04:00

161 lines
4.2 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports._processAndroidXML = _processAndroidXML;
exports.escapeAndroidString = escapeAndroidString;
exports.format = format;
exports.parseXMLAsync = parseXMLAsync;
exports.readXMLAsync = readXMLAsync;
exports.unescapeAndroidString = unescapeAndroidString;
exports.writeXMLAsync = writeXMLAsync;
function _fs() {
const data = _interopRequireDefault(require("fs"));
_fs = function () {
return data;
};
return data;
}
function _os() {
const data = require("os");
_os = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _xml2js() {
const data = require("xml2js");
_xml2js = function () {
return data;
};
return data;
}
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
async function writeXMLAsync(options) {
const xml = format(options.xml);
await _fs().default.promises.mkdir(_path().default.dirname(options.path), {
recursive: true
});
await _fs().default.promises.writeFile(options.path, xml);
}
async function readXMLAsync(options) {
let contents = '';
try {
contents = await _fs().default.promises.readFile(options.path, {
encoding: 'utf8',
flag: 'r'
});
} catch {
// catch and use fallback
}
const parser = new (_xml2js().Parser)();
const manifest = await parser.parseStringPromise(contents || options.fallback || '');
return _processAndroidXML(manifest);
}
function _processAndroidXML(manifest) {
// For strings.xml
if (Array.isArray(manifest?.resources?.string)) {
for (const string of manifest?.resources?.string) {
if (string.$.translatable === 'false' || string.$.translatable === false) {
continue;
}
string._ = unescapeAndroidString(string._);
}
}
return manifest;
}
async function parseXMLAsync(contents) {
const xml = await new (_xml2js().Parser)().parseStringPromise(contents);
return xml;
}
const stringTimesN = (n, char) => Array(n + 1).join(char);
function format(manifest, {
indentLevel = 2,
newline = _os().EOL
} = {}) {
let xmlInput;
if (typeof manifest === 'string') {
xmlInput = manifest;
} else if (manifest.toString) {
const builder = new (_xml2js().Builder)({
headless: true
});
// For strings.xml
if (Array.isArray(manifest?.resources?.string)) {
for (const string of manifest?.resources?.string) {
if (string.$.translatable === 'false' || string.$.translatable === false) {
continue;
}
string._ = escapeAndroidString(string._);
}
}
xmlInput = builder.buildObject(manifest);
return xmlInput;
} else {
throw new Error(`Invalid XML value passed in: ${manifest}`);
}
const indentString = stringTimesN(indentLevel, ' ');
let formatted = '';
const regex = /(>)(<)(\/*)/g;
const xml = xmlInput.replace(regex, `$1${newline}$2$3`);
let pad = 0;
xml.split(/\r?\n/).map(line => line.trim()).forEach(line => {
let indent = 0;
if (line.match(/.+<\/\w[^>]*>$/)) {
indent = 0;
} else if (line.match(/^<\/\w/)) {
if (pad !== 0) {
pad -= 1;
}
} else if (line.match(/^<\w([^>]*[^/])?>.*$/)) {
indent = 1;
} else {
indent = 0;
}
const padding = stringTimesN(pad, indentString);
formatted += padding + line + newline;
pad += indent;
});
return formatted.trim();
}
/**
* Escapes Android string literals, specifically characters `"`, `'`, `\`, `\n`, `\r`, `\t`
*
* @param value unescaped Android XML string literal.
*/
function escapeAndroidString(value) {
value = value.replace(/[\n\r\t'"@]/g, m => {
switch (m) {
case '"':
case "'":
case '@':
return '\\' + m;
case '\n':
return '\\n';
case '\r':
return '\\r';
case '\t':
return '\\t';
default:
throw new Error(`Cannot escape unhandled XML character: ${m}`);
}
});
if (value.match(/(^\s|\s$)/)) {
value = '"' + value + '"';
}
return value;
}
function unescapeAndroidString(value) {
return value.replace(/\\(.)/g, '$1');
}
//# sourceMappingURL=XML.js.map