From 4479cd489bca2d418af03a0fc8fe30694a0eb670 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 1 Nov 2024 07:35:53 +0300 Subject: [PATCH 1/5] nice one key doesnt fit in display fully --- lib/subghz/protocols/nice_flor_s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index 8694ec4c1..8e007582b 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -865,7 +865,7 @@ void subghz_protocol_decoder_nice_flor_s_get_string(void* context, FuriString* o furi_string_cat_printf( output, "%s %dbit\r\n" - "Key:0x%013llX%llX\r\n" + "Key:%013llX%llX\r\n" "Sn:%05lX\r\n" "Cnt:%04lX Btn:%02X\r\n", NICE_ONE_NAME, From eae8ef23dff2da88150231bca43cb0eddb58c89f Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 1 Nov 2024 07:43:07 +0300 Subject: [PATCH 2/5] move things in changelog --- CHANGELOG.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e88a22b2e..ccc30823d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,6 @@ - Frequency analyzer fixes and improvements: - **Enforce int module** (like in OFW) usage due to lack of required hardware on external boards (PathIsolate (+rf switch for multiple paths)) and incorrect usage and/or understanding the purpose of frequency analyzer app by users, it should be used only to get frequency of the remote placed around 1-10cm around flipper's left corner - **Fix possible GSM mobile towers signal interference** by limiting upper frequency to 920mhz max - - Fix duplicated frequency lists and use user config for nearest frequency selector too - Fix buttons logic, **fix crash** - Protocol improvements: - **Keeloq: Monarch full support, with add manually option** (thanks @ashphx !) @@ -12,36 +11,36 @@ - Hollarm add more button codes (thanks to @mishamyte for captures) - Misc: - Add extra settings to disable GPIO pins control used for external modules amplifiers and/or LEDs (in radio settings menu with debug ON) - - Code cleanup and fix for rare dupicated "Data" field cases - NFC: - Read Ultralight block by block (**fix password protected MFUL reading issue**) (by @mishamyte | PR #825 #826) - **Update NDEF parser** (SLIX and MFC support) (by @luu176 and @jaylikesbunda and @Willy-JL) - OFW PR 3822: **MIFARE Classic Key Recovery Improvements** (by @noproto) - - OFW PR 3930: NFC Emulation freeze (by @RebornedBrain) - - OFW PR 3885: Add API to enforce ISO15693 mode (by @aaronjamt) - - OFW: iso14443_4a improvements (by @RebornedBrain) - - OFW: Plantain parser improvements (by @assasinfil) & fixes (by @mxcdoam) - - OFW: Moscow social card parser (by @assasinfil) - - OFW: NFC: H World Hotel Chain Room Key Parser - - OFW: NFC Parser for Tianjin Railway Transit - - OFW: NFC TRT Parser: Additional checks to prevent false positives + - OFW PR 3930: NFC Emulation freeze fix (by @RebornedBrain) + - OFW: H World Hotel Chain Room Key Parser + - OFW: Parser for Tianjin Railway Transit - New keys in system dict - Infrared: - **Add LEDs universal remote** (DB by @amec0e) - Update universal remote assets (by @amec0e | PR #813 #816) - JS: - - OFW: JS modules -> **Breaking API change** + - OFW: JS modules & SDK -> **Breaking API change** - **Backporting custom features** (read about most of the changes after other changes section) (by @xMasterX and @Willy-JL) - - Add i2c module (by @jamisonderek) - - Add SPI module (by @jamisonderek) -* OFW: FuriHal, drivers: rework gauge initialization routine -> **Downgrade to older releases will break battery UI percent indicator, upgrade to this or newer version to restore** + - Add i2c & SPI module (by @jamisonderek) +* OFW: FuriHal, drivers: rework gauge initialization routine -> **Downgrade to older releases may break battery UI percent indicator, upgrade to this or newer version to restore** * OFW: heap: increased size -> **More free RAM!!** * OFW: New layout for BadUSB (es-LA) * OFW: Require PIN on boot * Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev) ## Other changes +* SubGHz: Freq analyzer - Fix duplicated frequency lists and use user config for nearest frequency selector too +* SubGHz: Code cleanup and fix for rare dupicated (Data) field cases +* OFW: NFC TRT Parser: Additional checks to prevent false positives +* OFW PR 3885: NFC: Add API to enforce ISO15693 mode (by @aaronjamt) +* OFW: NFC: iso14443_4a improvements (by @RebornedBrain) +* OFW: NFC: Plantain parser improvements (by @assasinfil) & fixes (by @mxcdoam) +* OFW: NFC: Moscow social card parser (by @assasinfil) * OFW: fix: npm deps -* OFW: 目覚め時計 +* OFW: 目覚め時計 (Added alarm option and clock settings) * OFW: JS: Backport and more additions & fixes * OFW: nfc: add Caltrain zones for Clipper * OFW: Update unit tests docs From 79caf7bf72869e124cd31fe7d7065ecb94b0a26d Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:49:46 +0300 Subject: [PATCH 3/5] Add js sdk changes With type declarations and various missing parts added by Willy-JL --- applications/system/js_app/js_modules.c | 9 ++ .../js_app/modules/js_subghz/js_subghz.c | 2 +- .../js_app/packages/create-fz-app/README.md | 10 +- .../packages/create-fz-app/package.json | 13 +- .../packages/create-fz-app/template/index.ts | 6 +- .../create-fz-app/template/package.json | 6 +- .../create-fz-app/template/tsconfig.json | 5 +- .../system/js_app/packages/fz-sdk/README.md | 19 ++- .../packages/fz-sdk/blebeacon/index.d.ts | 41 ++++++ .../js_app/packages/fz-sdk/flipper/index.d.ts | 2 +- .../system/js_app/packages/fz-sdk/global.d.ts | 7 + .../js_app/packages/fz-sdk/i2c/index.d.ts | 6 + .../js_app/packages/fz-sdk/package.json | 13 +- .../system/js_app/packages/fz-sdk/sdk.js | 8 +- .../js_app/packages/fz-sdk/spi/index.d.ts | 6 + .../js_app/packages/fz-sdk/subghz/index.d.ts | 64 +++++++++ .../js_app/packages/fz-sdk/usbdisk/index.d.ts | 24 ++++ .../js_app/packages/fz-sdk/vgm/index.d.ts | 32 +++++ .../js_app/packages/fz-sdk/widget/index.d.ts | 131 ++++++++++++++++++ 19 files changed, 378 insertions(+), 26 deletions(-) create mode 100644 applications/system/js_app/packages/fz-sdk/blebeacon/index.d.ts create mode 100644 applications/system/js_app/packages/fz-sdk/subghz/index.d.ts create mode 100644 applications/system/js_app/packages/fz-sdk/usbdisk/index.d.ts create mode 100644 applications/system/js_app/packages/fz-sdk/vgm/index.d.ts create mode 100644 applications/system/js_app/packages/fz-sdk/widget/index.d.ts diff --git a/applications/system/js_app/js_modules.c b/applications/system/js_app/js_modules.c index bffa553a8..429c01090 100644 --- a/applications/system/js_app/js_modules.c +++ b/applications/system/js_app/js_modules.c @@ -267,6 +267,15 @@ void js_check_sdk_compatibility(struct mjs* mjs) { static const char* extra_features[] = { "baseline", // dummy "feature" + + // extra modules + "blebeacon", + "i2c", + "spi", + "subghz", + "usbdisk", + "vgm", + "widget", }; /** diff --git a/applications/system/js_app/modules/js_subghz/js_subghz.c b/applications/system/js_app/modules/js_subghz/js_subghz.c index 051566aec..f7065d38c 100644 --- a/applications/system/js_app/modules/js_subghz/js_subghz.c +++ b/applications/system/js_app/modules/js_subghz/js_subghz.c @@ -223,7 +223,7 @@ static void js_subghz_transmit_file(struct mjs* mjs) { // - "repeat" as variable and loop in this code applies to RAW files only // parsed files handle repeat in protocol layer instead // We keep 0 as default, or literal value if specified by user - // If user did not specify, -1 is detected below, and we use: + // If user did not specify, 0 is detected below, and we use: // - 1 repeat for RAW // - 10 repeats for parsed, which is passed to protocol, and we loop once here uint32_t repeat = 0; diff --git a/applications/system/js_app/packages/create-fz-app/README.md b/applications/system/js_app/packages/create-fz-app/README.md index cf6ddbc91..97f22a4cc 100644 --- a/applications/system/js_app/packages/create-fz-app/README.md +++ b/applications/system/js_app/packages/create-fz-app/README.md @@ -1,11 +1,15 @@ -# Flipper Zero JavaScript SDK Wizard +# Flipper Unleashed Firmware JavaScript SDK Wizard This package contains an interactive wizard that lets you scaffold a JavaScript -application for Flipper Zero. +application for Flipper Zero using the Custom Unleashed Firmware JS SDK. + +This is a fork of the [Official Flipper Zero JS SDK Wizard](https://www.npmjs.com/package/@flipperdevices/create-fz-app), +configured to use the [Unleashed FW JavaScript SDK]((https://www.npmjs.com/package/@darkflippers/fz-sdk-ul)) instead. +No other changes are included. ## Getting started Create your application using the interactive wizard: ```shell -npx @flipperdevices/create-fz-app@latest +npx @darkflippers/create-fz-app-ul@latest ``` Then, enter the directory with your application and launch it: diff --git a/applications/system/js_app/packages/create-fz-app/package.json b/applications/system/js_app/packages/create-fz-app/package.json index 216423396..068260de9 100644 --- a/applications/system/js_app/packages/create-fz-app/package.json +++ b/applications/system/js_app/packages/create-fz-app/package.json @@ -1,10 +1,15 @@ { - "name": "@flipperdevices/create-fz-app", - "version": "0.1.0", - "description": "Template package for JS apps Flipper Zero", + "name": "@darkflippers/create-fz-app-ul", + "version": "0.1.1", + "description": "Template package for JS apps for Flipper Zero using Unleashed Firmware JS SDK", "bin": "index.js", "type": "module", "keywords": [ + "unleashed", + "unleashed firmware", + "ul", + "darkflippers", + "flipper cfw js", "flipper", "flipper zero" ], @@ -12,7 +17,7 @@ "license": "GPL-3.0-only", "repository": { "type": "git", - "url": "git+https://github.com/flipperdevices/flipperzero-firmware.git", + "url": "git+https://github.com/DarkFlippers/unleashed-firmware.git", "directory": "applications/system/js_app/packages/create-fz-app" }, "dependencies": { diff --git a/applications/system/js_app/packages/create-fz-app/template/index.ts b/applications/system/js_app/packages/create-fz-app/template/index.ts index 6291e3e13..430705e75 100644 --- a/applications/system/js_app/packages/create-fz-app/template/index.ts +++ b/applications/system/js_app/packages/create-fz-app/template/index.ts @@ -1,9 +1,9 @@ // import modules // caution: `eventLoop` HAS to be imported before `gui`, and `gui` HAS to be // imported before any `gui` submodules. -import * as eventLoop from "@flipperdevices/fz-sdk/event_loop"; -import * as gui from "@flipperdevices/fz-sdk/gui"; -import * as dialog from "@flipperdevices/fz-sdk/gui/dialog"; +import * as eventLoop from "@darkflippers/fz-sdk-ul/event_loop"; +import * as gui from "@darkflippers/fz-sdk-ul/gui"; +import * as dialog from "@darkflippers/fz-sdk-ul/gui/dialog"; // a common pattern is to declare all the views that your app uses on one object const views = { diff --git a/applications/system/js_app/packages/create-fz-app/template/package.json b/applications/system/js_app/packages/create-fz-app/template/package.json index 7acdeccaa..211411c73 100644 --- a/applications/system/js_app/packages/create-fz-app/template/package.json +++ b/applications/system/js_app/packages/create-fz-app/template/package.json @@ -2,11 +2,11 @@ "name": "", "version": "1.0.0", "scripts": { - "build": "tsc && node node_modules/@flipperdevices/fz-sdk/sdk.js build", - "start": "npm run build && node node_modules/@flipperdevices/fz-sdk/sdk.js upload" + "build": "tsc && node node_modules/@darkflippers/fz-sdk-ul/sdk.js build", + "start": "npm run build && node node_modules/@darkflippers/fz-sdk-ul/sdk.js upload" }, "devDependencies": { - "@flipperdevices/fz-sdk": "^0.1", + "@darkflippers/fz-sdk-ul": "^0.1", "typescript": "^5.6.3" } } \ No newline at end of file diff --git a/applications/system/js_app/packages/create-fz-app/template/tsconfig.json b/applications/system/js_app/packages/create-fz-app/template/tsconfig.json index c7b83cd5d..a1db94c39 100644 --- a/applications/system/js_app/packages/create-fz-app/template/tsconfig.json +++ b/applications/system/js_app/packages/create-fz-app/template/tsconfig.json @@ -5,13 +5,14 @@ "module": "CommonJS", "noLib": true, "target": "ES2015", + "types": [], }, "files": [ - "./node_modules/@flipperdevices/fz-sdk/global.d.ts", + "./node_modules/@darkflippers/fz-sdk-ul/global.d.ts", ], "include": [ "./**/*.ts", - "./**/*.js" + "./**/*.js", ], "exclude": [ "./node_modules/**/*", diff --git a/applications/system/js_app/packages/fz-sdk/README.md b/applications/system/js_app/packages/fz-sdk/README.md index 3234f68aa..8bac450fb 100644 --- a/applications/system/js_app/packages/fz-sdk/README.md +++ b/applications/system/js_app/packages/fz-sdk/README.md @@ -1,11 +1,22 @@ -# Flipper Zero JavaScript SDK -This package contains official tooling and typings for developing Flipper Zero -applications in JavaScript. +# Flipper Unleashed FW JavaScript SDK +This package contains tooling and typings for developing Flipper Zero +applications in JavaScript for Unleashed Custom Firmware (based on official SDK). + +This is a fork of the [Official Flipper Zero JS SDK](https://www.npmjs.com/package/@flipperdevices/fz-sdk), +with added types for the extra features provided by the Unleashed firmware JavaScript API. + +Scripts made for Official Flipper Zero JS SDK will work on Unleashed Firmware too. +If you use extra features provided by Unleashed FW JS SDK, you are encouraged to use syntax like +`if (doesSdkSupport(["feature-name"])) { ... }` so that your JS app can work on Official +Firmware too, aswell as all other compliant Custom Firmwares. If some of those extra +features are essential to the functionality of your app, you can use `checkSdkFeatures(["feature1", "feature2"])` +near the beginning of your script, which will show a warning to the user that these features +are not available in their firmware distribution. ## Getting started Create your application using the interactive wizard: ```shell -npx @flipperdevices/create-fz-app@latest +npx @darkflippers/create-fz-app-ul@latest ``` Then, enter the directory with your application and launch it: diff --git a/applications/system/js_app/packages/fz-sdk/blebeacon/index.d.ts b/applications/system/js_app/packages/fz-sdk/blebeacon/index.d.ts new file mode 100644 index 000000000..b2b527a40 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/blebeacon/index.d.ts @@ -0,0 +1,41 @@ +/** + * Module for using the BLE extra beacon + * @version Available with JS feature `blebeacon` + * @module + */ + +/** + * @brief Check if the BLE beacon is active + */ +export declare function isActive(): boolean; + +/** + * @brief Set BLE beacon configuration + * @param mac The MAC address to use + * @param power The power level to use, in GapAdvPowerLevel scale: 0x00 (-40dBm) to 0x1F (+6dBm) + * @param minInterval Minimum advertisement interval + * @param maxInterval Maximum advertisement interval + */ +export declare function setConfig(mac: Uint8Array, power?: number, minInterval?: number, maxInterval?: number): void; + +/** + * @brief Set BLE beacon advertisement data + * @param data The advertisement data to use + */ +export declare function setData(data: Uint8Array): void; + +/** + * @brief Start BLE beacon + */ +export declare function start(): void; + +/** + * @brief Stop BLE beacon + */ +export declare function stop(): void; + +/** + * @brief Set whether the BLE beacon will remain active after the script exits + * @param keep True if BLE beacon should remain active after script exit + */ +export declare function keepAlive(keep: boolean): void; diff --git a/applications/system/js_app/packages/fz-sdk/flipper/index.d.ts b/applications/system/js_app/packages/fz-sdk/flipper/index.d.ts index 2dac4204b..f939f012b 100644 --- a/applications/system/js_app/packages/fz-sdk/flipper/index.d.ts +++ b/applications/system/js_app/packages/fz-sdk/flipper/index.d.ts @@ -26,7 +26,7 @@ export declare function getBatteryCharge(): number; * @warning Do **NOT** use this to check the presence or absence of features. If * you do, I'm gonna be sad :( Instead, refer to `checkSdkFeatures` and * other similar mechanisms. - * @note Original firmware reports `"flipperdevices"`. + * @note Unleashed firmware reports `"unleashed"`. / Official firmware reports `"flipperdevices"`. * @version Added in JS SDK 0.1 */ export declare const firmwareVendor: string; diff --git a/applications/system/js_app/packages/fz-sdk/global.d.ts b/applications/system/js_app/packages/fz-sdk/global.d.ts index d2e73f7de..ba6996f27 100644 --- a/applications/system/js_app/packages/fz-sdk/global.d.ts +++ b/applications/system/js_app/packages/fz-sdk/global.d.ts @@ -202,6 +202,13 @@ declare function chr(n: number): string | null; */ declare function require(module: string): any; +/** + * @brief Exit JavaScript with given message + * @param message The error message to show to user + * @version Added in JS SDK 0.1 + */ +declare function die(message: string): never; + /** * @brief mJS Foreign Pointer type * diff --git a/applications/system/js_app/packages/fz-sdk/i2c/index.d.ts b/applications/system/js_app/packages/fz-sdk/i2c/index.d.ts index ea0a640cb..7ce118fe5 100644 --- a/applications/system/js_app/packages/fz-sdk/i2c/index.d.ts +++ b/applications/system/js_app/packages/fz-sdk/i2c/index.d.ts @@ -1,3 +1,9 @@ +/** + * I2C bus communication + * @version Available with JS feature `i2c` + * @module + */ + /** * @brief Check if there is an I2C device ready on the bus * @param address The device address to check diff --git a/applications/system/js_app/packages/fz-sdk/package.json b/applications/system/js_app/packages/fz-sdk/package.json index 4d18f3f20..3dbfca258 100644 --- a/applications/system/js_app/packages/fz-sdk/package.json +++ b/applications/system/js_app/packages/fz-sdk/package.json @@ -1,8 +1,13 @@ { - "name": "@flipperdevices/fz-sdk", - "version": "0.1.1", - "description": "Type declarations and documentation for native JS modules available on Flipper Zero", + "name": "@darkflippers/fz-sdk-ul", + "version": "0.1.2", + "description": "Type declarations and documentation for native JS modules available on Unleashed Custom Firmware for Flipper Zero", "keywords": [ + "unleashed", + "unleashed firmware", + "ul", + "darkflippers", + "flipper unleashed fw sdk", "flipper", "flipper zero", "framework" @@ -11,7 +16,7 @@ "license": "GPL-3.0-only", "repository": { "type": "git", - "url": "git+https://github.com/flipperdevices/flipperzero-firmware.git", + "url": "git+https://github.com/DarkFlippers/unleashed-firmware.git", "directory": "applications/system/js_app/packages/fz-sdk" }, "type": "module", diff --git a/applications/system/js_app/packages/fz-sdk/sdk.js b/applications/system/js_app/packages/fz-sdk/sdk.js index 2eecf032d..4fa1a95a7 100644 --- a/applications/system/js_app/packages/fz-sdk/sdk.js +++ b/applications/system/js_app/packages/fz-sdk/sdk.js @@ -10,6 +10,9 @@ import json5 from "json5"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); +const cfwSdkName = "@darkflippers/fz-sdk-ul/"; +const ofwSdkName = "@flipperdevices/fz-sdk/"; + async function build(config) { await esbuild.build({ entryPoints: ["./dist/index.js"], @@ -19,7 +22,7 @@ async function build(config) { bundle: true, minify: config.minify, external: [ - "@flipperdevices/fz-sdk/*" + "@darkflippers/fz-sdk-ul/*" ], supported: { "array-spread": false, @@ -74,6 +77,9 @@ async function build(config) { let outContents = fs.readFileSync(config.output, "utf8"); outContents = "let exports = {};\n" + outContents; + // Transform CFW SDK name to OFW SDK name so all firmwares understand it + outContents = outContents.replaceAll(`require("${cfwSdkName}`, `require("${ofwSdkName}`); + if (config.enforceSdkVersion) { const version = json5.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version; let [major, minor, _] = version.split("."); diff --git a/applications/system/js_app/packages/fz-sdk/spi/index.d.ts b/applications/system/js_app/packages/fz-sdk/spi/index.d.ts index 8d72bc29c..e4bb7774b 100644 --- a/applications/system/js_app/packages/fz-sdk/spi/index.d.ts +++ b/applications/system/js_app/packages/fz-sdk/spi/index.d.ts @@ -1,3 +1,9 @@ +/** + * SPI bus communication + * @version Available with JS feature `spi` + * @module + */ + /** * @brief Acquire SPI bus */ diff --git a/applications/system/js_app/packages/fz-sdk/subghz/index.d.ts b/applications/system/js_app/packages/fz-sdk/subghz/index.d.ts new file mode 100644 index 000000000..9af9e67a9 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/subghz/index.d.ts @@ -0,0 +1,64 @@ +/** + * Module for using Sub-GHz transciever + * @version Available with JS feature `subghz` + * @module + */ + +/** + * @brief Initialize Sub-GHz module + */ +export declare function setup(): void; + +/** + * @brief Deinitialize Sub-GHz module + */ +export declare function end(): void; + +/** + * @brief Set radio to receive mode + */ +export declare function setRx(): void; + +/** + * @brief Set radio to idle mode + */ +export declare function setIdle(): void; + +/** + * @brief Return current RSSI on current frequency, or undefined if radio is not in receive mode + */ +export declare function getRssi(): number | undefined; + +type RadioState = "RX" | "TX" | "IDLE" | ""; + +/** + * @brief Get current radio mode/state + */ +export declare function getState(): RadioState; + +/** + * @brief Get currently selected frequency + */ +export declare function getFrequency(): number; + +/** + * @brief Change current frequency, radio must be in idle mode + * + * Returns the effective frequency, since radio module cant use all precise + * values and instead chooses closest one available + * + * @param frequency What frequency to use + */ +export declare function setFrequency(frequency: number): number; + +/** + * @brief Check whether the radio module in use is internal or external + */ +export declare function isExternal(): boolean; + +/** + * @brief Transmit a .sub file, return true on success or error on failure + * @param path What .sub file to transmit + * @param repeat How many times to repeat the signal + */ +export declare function transmitFile(path: string, repeat?: number): true; diff --git a/applications/system/js_app/packages/fz-sdk/usbdisk/index.d.ts b/applications/system/js_app/packages/fz-sdk/usbdisk/index.d.ts new file mode 100644 index 000000000..b9c5da5f7 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/usbdisk/index.d.ts @@ -0,0 +1,24 @@ +/** + * Module for USB mass storage emulation + * @version Available with JS feature `usbdisk` + * @module + */ + +/** + * @brief Start emulating mass storage device + * @param path The disk image to emulate + */ +export declare function start(path: string): void; + +/** + * @brief Stop emulating mass storage device + */ +export declare function stop(): void; + +/** + * @brief Check if the mass storage device was exected + * + * Useful as a loop condition with a delay, so UsbDisk keeps running until ejected + * + */ +export declare function wasEjected(): boolean; diff --git a/applications/system/js_app/packages/fz-sdk/vgm/index.d.ts b/applications/system/js_app/packages/fz-sdk/vgm/index.d.ts new file mode 100644 index 000000000..a6bef6f16 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/vgm/index.d.ts @@ -0,0 +1,32 @@ +/** + * Module for interactive with Flipper Video Game Module (VGM) + * @version Available with JS feature `vgm` + * @module + */ + +/** + * @brief Get current VGM pitch, or undefined if VGM not present + */ +export declare function getPitch(): number | undefined; + +/** + * @brief Get current VGM roll, or undefined if VGM not present + */ +export declare function getRoll(): number | undefined; + +/** + * @brief Get current VGM yaw, or undefined if VGM not present + */ +export declare function getYaw(): number | undefined; + +/** + * @brief Wait until yaw changed by specified amount + * + * Returns how much the yaw changed from initial value if it exceeded the + * specified yaw angle, or returns 0 if it was not exceeded within the timeout + * Or returns undefined if VGM is not present + * + * @param angle How much the yaw needs to change + * @param timeout Maximum time in milliseconds to wait for specified yaw change, default 3000ms + */ +export declare function deltaYaw(angle: number, timeout?: number): number | undefined; diff --git a/applications/system/js_app/packages/fz-sdk/widget/index.d.ts b/applications/system/js_app/packages/fz-sdk/widget/index.d.ts new file mode 100644 index 000000000..6644b38b6 --- /dev/null +++ b/applications/system/js_app/packages/fz-sdk/widget/index.d.ts @@ -0,0 +1,131 @@ +/** + * Displays a customizable Widget on screen + * @version Available with JS feature `widget` + * @module + */ + +type ComponentId = number; + +/** + * @brief Add a box component + * @param x Horizontal position + * @param y Vertical position + * @param w Width + * @param h Height + */ +export declare function addBox(x: number, y: number, w: number, h: number): ComponentId; + +/** + * @brief Add a circle component + * @param x Horizontal position + * @param y Vertical position + * @param r Radius + */ +export declare function addCircle(x: number, y: number, r: number): ComponentId; + +/** + * @brief Add a disc component + * @param x Horizontal position + * @param y Vertical position + * @param r Radius + */ +export declare function addDisc(x: number, y: number, r: number): ComponentId; + +/** + * @brief Add a dot component + * @param x Horizontal position + * @param y Vertical position + */ +export declare function addDot(x: number, y: number): ComponentId; + +/** + * @brief Add a frame component + * @param x Horizontal position + * @param y Vertical position + * @param w Width + * @param h Height + */ +export declare function addFrame(x: number, y: number, w: number, h: number): ComponentId; + +/** + * @brief Add a glyph component + * @param x Horizontal position + * @param y Vertical position + * @param ch ASCII character code (eg. `"C".charCodeAt(0)`) + */ +export declare function addGlyph(x: number, y: number, ch: number): ComponentId; + +/** + * @brief Add a line component + * @param x1 Horizontal position 1 + * @param y1 Vertical position 1 + * @param x2 Horizontal position 2 + * @param y2 Vertical position 2 + */ +export declare function addLine(x1: number, y1: number, x2: number, y2: number): ComponentId; + +/** + * @brief Add a rounded box component + * @param x Horizontal position + * @param y Vertical position + * @param w Width + * @param h Height + * @param r Radius + */ +export declare function addRbox(x: number, y: number, w: number, h: number, r: number): ComponentId; + +/** + * @brief Add a rounded frame component + * @param x Horizontal position + * @param y Vertical position + * @param w Width + * @param h Height + * @param r Radius + */ +export declare function addRframe(x: number, y: number, w: number, h: number, r: number): ComponentId; + +/** + * @brief Add a text component + * @param x Horizontal position + * @param y Vertical position + * @param font What font to use, Primary or Secondary + * @param text Text to display + */ +export declare function addText(x: number, y: number, font: "Primary" | "Secondary", text: string): ComponentId; + +type XbmId = number; + +/** + * @brief Add an xbm image component + * @param x Horizontal position + * @param y Vertical position + * @param index Loaded xbm id to use + */ +export declare function addXbm(x: number, y: number, index: XbmId): ComponentId; + +/** + * @brief Load an xbm image sprite + * @param path Xbm file to load + */ +export declare function loadImageXbm(path: string): XbmId; + +/** + * @brief Remove a component + * @param id Component id to remove + */ +export declare function remove(id: ComponentId): boolean; + +/** + * @brief Check if the widget view is shown + */ +export declare function isOpen(): boolean; + +/** + * @brief Show the widget view + */ +export declare function show(): void; + +/** + * @brief Close the widget view + */ +export declare function close(): void; From 462ab255a16a6edf9473ddad0990f5c52baa7861 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Tue, 5 Nov 2024 09:52:24 +0300 Subject: [PATCH 4/5] upd examples --- .../apps/Scripts/js_examples/blebeacon.js | 3 ++ .../examples/apps/Scripts/js_examples/i2c.js | 3 ++ .../examples/apps/Scripts/js_examples/spi.js | 6 +++- .../apps/Scripts/js_examples/subghz.js | 3 ++ .../apps/Scripts/js_examples/usbdisk.js | 29 +++++++++++++++++++ .../apps/Scripts/js_examples/widget.js | 11 ++++--- 6 files changed, 50 insertions(+), 5 deletions(-) diff --git a/applications/system/js_app/examples/apps/Scripts/js_examples/blebeacon.js b/applications/system/js_app/examples/apps/Scripts/js_examples/blebeacon.js index 1187f1c20..c1a6c1d16 100644 --- a/applications/system/js_app/examples/apps/Scripts/js_examples/blebeacon.js +++ b/applications/system/js_app/examples/apps/Scripts/js_examples/blebeacon.js @@ -1,3 +1,6 @@ +// Script cannot work without blebeacon module so check before +checkSdkFeatures(["blebeacon"]); + let blebeacon = require("blebeacon"); // Stop if previous background beacon is active diff --git a/applications/system/js_app/examples/apps/Scripts/js_examples/i2c.js b/applications/system/js_app/examples/apps/Scripts/js_examples/i2c.js index 456b44ccd..5c71cfe4e 100644 --- a/applications/system/js_app/examples/apps/Scripts/js_examples/i2c.js +++ b/applications/system/js_app/examples/apps/Scripts/js_examples/i2c.js @@ -1,3 +1,6 @@ +// Script cannot work without i2c module so check before +checkSdkFeatures(["i2c"]); + // Connect an 24C32N EEPROM to the I2C bus of the board. SDA=pin 15, SCL=pin 16, VCC=pin 9, GND=pin 8. let i2c = require("i2c"); diff --git a/applications/system/js_app/examples/apps/Scripts/js_examples/spi.js b/applications/system/js_app/examples/apps/Scripts/js_examples/spi.js index 810637b3b..225b7b139 100644 --- a/applications/system/js_app/examples/apps/Scripts/js_examples/spi.js +++ b/applications/system/js_app/examples/apps/Scripts/js_examples/spi.js @@ -1,3 +1,6 @@ +// Script cannot work without spi module so check before +checkSdkFeatures(["spi"]); + // Connect a w25q32 SPI device to the Flipper Zero. // D1=pin 2 (MOSI), SLK=pin 5 (SCK), GND=pin 8 (GND), D0=pin 3 (MISO), CS=pin 4 (CS), VCC=pin 9 (3V3) let spi = require("spi"); @@ -5,8 +8,9 @@ let spi = require("spi"); // Display textbox so user can scroll to see all output. let eventLoop = require("event_loop"); let gui = require("gui"); +let textBoxView = require("gui/text_box"); let text = "SPI demo\n"; -let textBox = require("gui/text_box").makeWith({ +let textBox = textBoxView.makeWith({ focus: "end", font: "text", text: text, diff --git a/applications/system/js_app/examples/apps/Scripts/js_examples/subghz.js b/applications/system/js_app/examples/apps/Scripts/js_examples/subghz.js index b5e54bac6..d53635b50 100644 --- a/applications/system/js_app/examples/apps/Scripts/js_examples/subghz.js +++ b/applications/system/js_app/examples/apps/Scripts/js_examples/subghz.js @@ -1,3 +1,6 @@ +// Script cannot work without subghz module so check before +checkSdkFeatures(["subghz"]); + let subghz = require("subghz"); subghz.setup(); diff --git a/applications/system/js_app/examples/apps/Scripts/js_examples/usbdisk.js b/applications/system/js_app/examples/apps/Scripts/js_examples/usbdisk.js index 7d148ab4c..8bf78dde6 100644 --- a/applications/system/js_app/examples/apps/Scripts/js_examples/usbdisk.js +++ b/applications/system/js_app/examples/apps/Scripts/js_examples/usbdisk.js @@ -1,10 +1,39 @@ +// Script cannot work without usbdisk module so check before +checkSdkFeatures(["usbdisk"]); + let usbdisk = require("usbdisk"); +let storage = require("storage"); + +let imagePath = "/ext/apps_data/mass_storage/128MB.img"; +let imageSize = 128 * 1024 * 1024; + +let imageExisted = storage.fileExists(imagePath); +if (imageExisted) { + print("Disk image '128MB' already exists"); +} else { + // CreateImage isn't necessary to overall function, check when its used not at script start + if (doesSdkSupport(["usbdisk-createimage"])) { + print("Creating disk image '128MB'..."); + usbdisk.createImage(imagePath, imageSize); + } else { + die("Disk image '128MB' not present, can't auto-create"); + } +} + print("Starting UsbDisk..."); usbdisk.start("/ext/apps_data/mass_storage/128MB.img"); + print("Started, waiting until ejected..."); while (!usbdisk.wasEjected()) { delay(1000); } + print("Ejected, stopping UsbDisk..."); usbdisk.stop(); + +if (!imageExisted) { + print("Removing disk image..."); + storage.remove(imagePath); +} + print("Done"); \ No newline at end of file diff --git a/applications/system/js_app/examples/apps/Scripts/js_examples/widget.js b/applications/system/js_app/examples/apps/Scripts/js_examples/widget.js index 4ff11e441..32ba96d1b 100644 --- a/applications/system/js_app/examples/apps/Scripts/js_examples/widget.js +++ b/applications/system/js_app/examples/apps/Scripts/js_examples/widget.js @@ -1,17 +1,20 @@ +// Script cannot work without widget module so check before +checkSdkFeatures(["widget"]); + let widget = require("widget"); let demo_seconds = 30; -print("Loading file", __filepath); -print("From directory", __dirpath); +print("Loading file", __filename); +print("From directory", __dirname); // addText supports "Primary" and "Secondary" font sizes. widget.addText(10, 10, "Primary", "Example JS widget"); widget.addText(10, 20, "Secondary", "Example widget from JS!"); // load a Xbm file from the same directory as this script. -widget.addText(0, 30, "Secondary", __filepath); -let logo = widget.loadImageXbm(__dirpath + "/widget-js.fxbm"); +widget.addText(0, 30, "Secondary", __filename); +let logo = widget.loadImageXbm(__dirname + "/widget-js.fxbm"); // add a line (x1, y1, x2, y2) widget.addLine(10, 35, 120, 35); From 3ef283824dd37da908b4dab18ec0f064d1f881ea Mon Sep 17 00:00:00 2001 From: WillyJL <49810075+Willy-JL@users.noreply.github.com> Date: Tue, 5 Nov 2024 07:32:24 +0000 Subject: [PATCH 5/5] FBT: Optimize icons blob -4KB DFU, scrub unused icons (#291) * Unused icons to check later * Exclude disabled icons from firmware * Format * Also report free flash in gh comment * Fix free flash calc * Fix? * Fix?? * Split to next line * Remove dead icons * Some spring cleaning of icons cooker * Improve unused icons script * Disable icons that cant be used in asset packs * These will need a workaround for external * Revert "These will need a workaround for external" This reverts commit fb23d97952a7f10f263ed8c8b339443d831a5b06. * Here's the workaround: split assets lib now there is "assets" and "fwassets" firmware links with fwassets and includes all icons however not all of them are exposed to api if an app needs a firmware icon not in api, it can use fap_libs=["assets"] this will link against this dummy assets lib it only contains the icons that arent exposed to api this way, an app using assets lib will still benefit from asset packs but at same time, we can remove pointless icons from dfu blob * Update changelog --- .github/workflows/build.yml | 16 ++- CHANGELOG.md | 7 +- applications/main/nfc/application.fam | 2 +- applications/settings/about/application.fam | 1 + .../power_settings_app/application.fam | 1 + .../settings/storage_settings/application.fam | 1 + applications/system/js_app/application.fam | 2 + assets/SConscript | 26 ++++- assets/icons/Infrared/Play_25x27.png | Bin 137 -> 0 bytes assets/icons/Infrared/Play_hvr_25x27.png | Bin 128 -> 0 bytes assets/icons/Infrared/hourglass0_24x24.png | Bin 138 -> 0 bytes assets/icons/Infrared/hourglass1_24x24.png | Bin 143 -> 0 bytes assets/icons/Infrared/hourglass2_24x24.png | Bin 137 -> 0 bytes assets/icons/Infrared/hourglass3_24x24.png | Bin 136 -> 0 bytes assets/icons/Infrared/hourglass4_24x24.png | Bin 144 -> 0 bytes assets/icons/Infrared/hourglass5_24x24.png | Bin 136 -> 0 bytes assets/icons/Infrared/hourglass6_24x24.png | Bin 145 -> 0 bytes assets/icons/PIN/Pin_cell_13x13.png | Bin 79 -> 0 bytes scripts/assets.py | 92 +++++++++++------- scripts/check_unused_icons.py | 39 ++++++++ scripts/fbt_tools/fbt_assets.py | 16 ++- scripts/fbt_tools/fbt_extapps.py | 1 + targets/f7/api_symbols.csv | 54 +++++----- targets/f7/target.json | 2 +- 24 files changed, 183 insertions(+), 77 deletions(-) delete mode 100644 assets/icons/Infrared/Play_25x27.png delete mode 100644 assets/icons/Infrared/Play_hvr_25x27.png delete mode 100644 assets/icons/Infrared/hourglass0_24x24.png delete mode 100644 assets/icons/Infrared/hourglass1_24x24.png delete mode 100644 assets/icons/Infrared/hourglass2_24x24.png delete mode 100644 assets/icons/Infrared/hourglass3_24x24.png delete mode 100644 assets/icons/Infrared/hourglass4_24x24.png delete mode 100644 assets/icons/Infrared/hourglass5_24x24.png delete mode 100644 assets/icons/Infrared/hourglass6_24x24.png delete mode 100644 assets/icons/PIN/Pin_cell_13x13.png create mode 100755 scripts/check_unused_icons.py diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d221e9524..fcad25108 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -128,11 +128,22 @@ jobs: dfu_size_new=$(du --apparent-size -B 1 artifacts/flipper-z-${TARGET}-full-*.dfu | cut -f1) dfu_size_dev=$(du --apparent-size -B 1 dev.dfu | cut -f1) dfu_size_diff=$((dfu_size_new - dfu_size_dev)) - DFU_SIZE=$(echo ${dfu_size_new}B | sed -r 's/^([0-9]+)([0-9]{2})([0-9])B/\1.\2K/') - DFU_DIFF=$(echo ${dfu_size_diff}B | sed -r 's/^(-?[0-9]+)([0-9]{2})([0-9])B/\1.\2K/' | sed -r 's/^([^-])/+\1/') + DFU_SIZE=$(echo $dfu_size_new | numfmt --to=iec --format=%.2f) + DFU_DIFF=$(echo $dfu_size_diff | numfmt --to=iec --format=%.2f | sed -r 's/^([^-])/+\1/') echo "DFU_SIZE=$DFU_SIZE" >> $GITHUB_ENV echo "DFU_DIFF=$DFU_DIFF" >> $GITHUB_ENV + tar xzf build/core2_firmware.tgz + radio_addr=$(jq -r '.copro.radio.files[0].address' core2_firmware/Manifest.json) + flash_base=0x8000000 + min_gap=$((2 * 4 * 1024)) + flash_free_total=$((radio_addr - flash_base - dfu_size_new)) + flash_free_usable=$((flash_free_total - min_gap)) + FLASH_FREE=$(echo $flash_free_total | numfmt --to=iec --format=%.2f) + FLASH_USABLE=$(echo $flash_free_usable | numfmt --to=iec --format=%.2f) + echo "FLASH_FREE=$FLASH_FREE" >> $GITHUB_ENV + echo "FLASH_USABLE=$FLASH_USABLE" >> $GITHUB_ENV + - name: "Upload artifacts to update server" env: INDEXER_URL: ${{ secrets.INDEXER_URL }} @@ -170,6 +181,7 @@ jobs: - [☁️ Flipper Lab/App](https://lab.flipper.net/?url=${{secrets.INDEXER_URL}}/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=mntm-${{steps.names.outputs.branch_name}}&version=${{steps.names.outputs.commit_sha}}) - [📦 qFlipper Package](${{secrets.INDEXER_URL}}/builds/firmware/${{steps.names.outputs.branch_name}}/flipper-z-${{steps.names.outputs.default_target}}-update-${{steps.names.outputs.suffix}}.tgz) - DFU Size: `${{ env.DFU_SIZE }}` (`${{ env.DFU_DIFF }}` from dev) + - Free Flash: `${{ env.FLASH_FREE }}` (`${{ env.FLASH_USABLE }}` usable) edit-mode: replace - name: Send devbuild webhook diff --git a/CHANGELOG.md b/CHANGELOG.md index 12b5fea2b..ab9defb1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -133,9 +133,6 @@ - UL: W5500 Ethernet: Various fixes and improvements (by @xMasterX) - OFW: SPI Mem Manager: Fixed UI rendering bug related to line breaks (by @portasynthinca3) - OFW: USB/BT Remote: Mouse clicker option to click as fast as possible (by @sumukhj1219) -- CLI: - - Print plugin name on load fail (by @Willy-JL) - - Move more commands as plugins on SD, refactor plugin wrapper (#276 by @Willy-JL) - NFC: - NDEF Parser: - Mifare Classic support (#265 by @luu176), protocol-agnostic rewrite and more improvements (#265 by @Willy-JL) @@ -166,6 +163,10 @@ - OFW: Add TCL 75S451 to TV universal remote (by @christhetech131) - OFW: Universal remote additions (by @jaylikesbunda) - OFW: Heavily Expand Universal Remotes (by @jaylikesbunda) +- CLI: + - Print plugin name on load fail (by @Willy-JL) + - Move more commands as plugins on SD, refactor plugin wrapper (#276 by @Willy-JL) +- FBT: Optimize icons blob, scrub unused icons (#291 by @Willy-JL) - OFW: BadKB: Improve ChromeOS and GNOME demo scripts (by @kowalski7cc) - OFW: GUI: Change dialog_ex text ownership model (by @skotopes) - OFW: CCID: App changes and improvements (by @kidbomb) diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 13c26b7aa..3878fc2e8 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -13,7 +13,7 @@ App( "!plugins", "!nfc_cli.c", ], - fap_libs=["mbedtls"], + fap_libs=["assets", "mbedtls"], fap_icon="icon.png", fap_category="NFC", ) diff --git a/applications/settings/about/application.fam b/applications/settings/about/application.fam index 055933544..e7b474c22 100644 --- a/applications/settings/about/application.fam +++ b/applications/settings/about/application.fam @@ -12,4 +12,5 @@ App( stack_size=1 * 1024, order=1000, fap_category="assets", + fap_libs=["assets"], ) diff --git a/applications/settings/power_settings_app/application.fam b/applications/settings/power_settings_app/application.fam index 65f90b14f..23cfdfabc 100644 --- a/applications/settings/power_settings_app/application.fam +++ b/applications/settings/power_settings_app/application.fam @@ -12,4 +12,5 @@ App( stack_size=1 * 1024, order=40, fap_category="assets", + fap_libs=["assets"], ) diff --git a/applications/settings/storage_settings/application.fam b/applications/settings/storage_settings/application.fam index eba847ddb..560f1f56c 100644 --- a/applications/settings/storage_settings/application.fam +++ b/applications/settings/storage_settings/application.fam @@ -8,4 +8,5 @@ App( stack_size=2 * 1024, order=30, fap_category="assets", + fap_libs=["assets"], ) diff --git a/applications/system/js_app/application.fam b/applications/system/js_app/application.fam index 988fedb03..6d2b4fe80 100644 --- a/applications/system/js_app/application.fam +++ b/applications/system/js_app/application.fam @@ -5,6 +5,7 @@ App( cdefines=["JS_RUNNER_FAP"], fap_icon="icon.png", fap_category="assets", + fap_libs=["assets"], entry_point="js_app", stack_size=2 * 1024, resources="examples", @@ -35,6 +36,7 @@ App( "modules/js_flipper.c", "modules/js_tests.c", ], + fap_libs=["assets"], ) App( diff --git a/assets/SConscript b/assets/SConscript index a5454fffa..7aefdc0a5 100644 --- a/assets/SConscript +++ b/assets/SConscript @@ -14,9 +14,26 @@ icons_path = ( if assetsenv["IS_BASE_FIRMWARE"] else assetsenv["ASSETS_WORK_DIR"] ) -icons = assetsenv.CompileIcons(icons_path, assetsenv["ASSETS_SRC_DIR"].Dir("icons")) +icons = assetsenv.CompileIcons( + icons_path, + assetsenv["ASSETS_SRC_DIR"].Dir("icons"), + fw_bundle=True, +) assetsenv.Alias("icons", icons) +# Extra icons lib so apps don't override asset packs to use fw icons not exposed to api +# Not used anywhere in code, apps still reference assets_icons.h, but if one of the +# icons they need is not exposed in api, they can link with fap_libs=["assets"] which +# will use this lib purely for linking as a drop-in for missing symbols. +# Should mean that apps made for OFW with fap_libs=["assets"], when compiled with +# this FBT, will still use asset packs at runtime and only link non-exposed icons. +if assetsenv["IS_BASE_FIRMWARE"]: + dropin_icons = assetsenv.CompileIcons( + assetsenv["ASSETS_WORK_DIR"], + assetsenv["ASSETS_SRC_DIR"].Dir("icons"), + icon_bundle_name="_assets_icons_dropin", + ) + # Protobuf .proto -> .c + .h proto_src = assetsenv.Glob("protobuf/*.proto", source=True) @@ -59,9 +76,14 @@ assetsenv.Alias("proto_ver", proto_ver) assets_parts = (icons, proto, dolphin_blocking, dolphin_internal, proto_ver) env.Replace(FW_ASSETS_HEADERS=assets_parts) -assetslib = assetsenv.Library("${FW_LIB_NAME}", assets_parts) +assetslib = assetsenv.Library("fw${FW_LIB_NAME}", assets_parts) assetsenv.Install("${LIB_DIST_DIR}", assetslib) +if assetsenv["IS_BASE_FIRMWARE"]: + dropin_parts = (dropin_icons, proto, dolphin_blocking, dolphin_internal, proto_ver) + dropin_assetslib = assetsenv.Library("${FW_LIB_NAME}", dropin_parts) + assetsenv.Install("${LIB_DIST_DIR}", dropin_assetslib) + # Resources for SD card if assetsenv["IS_BASE_FIRMWARE"]: diff --git a/assets/icons/Infrared/Play_25x27.png b/assets/icons/Infrared/Play_25x27.png deleted file mode 100644 index f1064d7b164140b9fc048e77956ad9c8789728f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^l0YoY2qYL5MoAt8QURVWjv*CuSPvfLZ3^QQF_ZuR diff --git a/assets/icons/Infrared/Play_hvr_25x27.png b/assets/icons/Infrared/Play_hvr_25x27.png deleted file mode 100644 index fa234ba172fb30e69115683a9d374e1406387c8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^l0YoY2qYL5MoAt8QtqBEjv*CuLeFdzY*1i0df|Dw zpnIW-Te67Tf+ZggFi8h5IptbB%_Ml$)5T8Be9Uq)HgLG^NWI>jzopr01!_wxc~qF diff --git a/assets/icons/Infrared/hourglass1_24x24.png b/assets/icons/Infrared/hourglass1_24x24.png deleted file mode 100644 index ef048a7bdab260080ce7c6458fc4c9a3a946a57d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143 zcmeAS@N?(olHy`uVBq!ia0vp^5+KY7Bp6QcFoXiBFi#i9kcv5~CpQYZ28g&`tX(I4 zxj}NPhOhSij`>21m>cDKIwU{$9q^jY6Jrwj(_>}uMG*%BfiFwybpJ`e=gZn>&1p6% qHE`$i1XYQ^i$|QNe>>=^e3<*0tjyFa!Eb(mZ1QyVb6Mw<&;$UKTroNT diff --git a/assets/icons/Infrared/hourglass2_24x24.png b/assets/icons/Infrared/hourglass2_24x24.png deleted file mode 100644 index 918bd79d869be1a4d5a2c6689cc237033ba408ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 137 zcmeAS@N?(olHy`uVBq!ia0vp^5+KY7Bp6QcFoXiB08bakkcv6FCpHQ?1cFDRxUX)i z(=g?!M9WD9q2LX!E>oGFYBU@=J2`cM;nIVqo{_Pt4fd6+`FutPfBbYUP}1N0>tgfY i+TC2{mN%y!Q#s6R(=72Xy)At&$O=zaKbLh*2~7ZC9xhq{ diff --git a/assets/icons/Infrared/hourglass4_24x24.png b/assets/icons/Infrared/hourglass4_24x24.png deleted file mode 100644 index 7ed58a5b4b0e92001f865ceb21af031bc7d8ea38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144 zcmeAS@N?(olHy`uVBq!ia0vp^5+KY7Bp6QcFoXiBa8DPW0o68rx#%5Z6MpZT}^1js5+S3j3^P6TPj=N$AxAsa*?OUm95H&5xM88q +#include #include """ ICONS_TEMPLATE_H_ICON_NAME = "extern const Icon {name};\n" +ICONS_TEMPLATE_H_ICON_PATHS = """ +typedef struct { + const Icon* icon; + const char* path; +} IconPath; + +extern const IconPath ICON_PATHS[]; +extern const size_t ICON_PATHS_COUNT; +""" ICONS_TEMPLATE_C_HEADER = """#include "{assets_filename}.h" @@ -25,6 +34,15 @@ ICONS_TEMPLATE_C_HEADER = """#include "{assets_filename}.h" ICONS_TEMPLATE_C_FRAME = "const uint8_t {name}[] = {data};\n" ICONS_TEMPLATE_C_DATA = "const uint8_t* const {name}[] = {data};\n" ICONS_TEMPLATE_C_ICONS = "const Icon {name} = {{.width={width},.height={height},.frame_count={frame_count},.frame_rate={frame_rate},.frames=_{name}}};\n" +ICONS_TEMPLATE_C_ICON_PATH = ' {{&{name}, "{path}"}},\n' +ICONS_TEMPLATE_C_ICON_PATHS = """ +const IconPath ICON_PATHS[] = {{ +#ifndef FURI_RAM_EXEC +{icon_paths} +#endif +}}; +const size_t ICON_PATHS_COUNT = COUNT_OF(ICON_PATHS); +""" MAX_IMAGE_WIDTH = 2**16 - 1 MAX_IMAGE_HEIGHT = 2**16 - 1 @@ -45,6 +63,22 @@ class Main(App): required=False, default="assets_icons", ) + self.parser_icons.add_argument( + "--fw-bundle", + dest="fw_bundle", + help="Bundle all icons and path info, only for use in firmware blob", + default=0, + type=int, + required=False, + ) + self.parser_icons.add_argument( + "--add-include", + dest="add_include", + help="Add assets_icons.h include drop-in for apps", + default=0, + type=int, + required=False, + ) self.parser_icons.set_defaults(func=self.icons) @@ -138,7 +172,6 @@ class Main(App): ) icons = [] paths = [] - is_main_assets = self.args.filename == "assets_icons" symbols = pathlib.Path(__file__).parent.parent if "UFBT_HOME" in os.environ: symbols /= "sdk_headers/f7_sdk" @@ -154,7 +187,8 @@ class Main(App): if "frame_rate" in filenames: self.logger.debug("Folder contains animation") icon_name = "A_" + os.path.split(dirpath)[1].replace("-", "_") - if not is_main_assets and api_has_icon(icon_name): + icon_in_api = api_has_icon(icon_name) + if not self.args.fw_bundle and icon_in_api: self.logger.info( f"{self.args.filename}: ignoring duplicate icon {icon_name}" ) @@ -193,8 +227,9 @@ class Main(App): ) icons_c.write("\n") icons.append((icon_name, width, height, frame_rate, frame_count)) - p = dirpath.removeprefix(self.args.input_directory)[1:] - paths.append((icon_name, p.replace("\\", "/"))) + if self.args.fw_bundle and icon_in_api: + path = dirpath.removeprefix(self.args.input_directory)[1:] + paths.append((icon_name, path.replace("\\", "/"))) else: # process icons for filename in filenames: @@ -204,7 +239,8 @@ class Main(App): icon_name = "I_" + "_".join(filename.split(".")[:-1]).replace( "-", "_" ) - if not is_main_assets and api_has_icon(icon_name): + icon_in_api = api_has_icon(icon_name) + if not self.args.fw_bundle and icon_in_api: self.logger.info( f"{self.args.filename}: ignoring duplicate icon {icon_name}" ) @@ -222,8 +258,11 @@ class Main(App): ) icons_c.write("\n") icons.append((icon_name, width, height, 0, 1)) - p = fullfilename.removeprefix(self.args.input_directory)[1:] - paths.append((icon_name, p.replace("\\", "/").rsplit(".", 1)[0])) + if self.args.fw_bundle and icon_in_api: + path = fullfilename.removeprefix(self.args.input_directory)[1:] + paths.append( + (icon_name, path.replace("\\", "/").rsplit(".", 1)[0]) + ) # Create array of images: self.logger.debug("Finalizing source file") for name, width, height, frame_rate, frame_count in icons: @@ -236,21 +275,14 @@ class Main(App): frame_count=frame_count, ) ) - if is_main_assets: - icons_c.write( - """ -const IconPath ICON_PATHS[] = { -#ifndef FURI_RAM_EXEC -""" - ) - for name, path in paths: - icons_c.write(f' {{&{name}, "{path}"}},\n') - icons_c.write( - """#endif -}; -const size_t ICON_PATHS_COUNT = COUNT_OF(ICON_PATHS); -""" + if not self.args.fw_bundle: + icons_c.write("\n") + else: + icon_paths = "\n".join( + ICONS_TEMPLATE_C_ICON_PATH.format(name=name, path=path) + for name, path in paths ) + icons_c.write(ICONS_TEMPLATE_C_ICON_PATHS.format(icon_paths=icon_paths)) icons_c.close() # Create Public Header @@ -263,19 +295,9 @@ const size_t ICON_PATHS_COUNT = COUNT_OF(ICON_PATHS); icons_h.write(ICONS_TEMPLATE_H_HEADER) for name, width, height, frame_rate, frame_count in icons: icons_h.write(ICONS_TEMPLATE_H_ICON_NAME.format(name=name)) - if is_main_assets: - icons_h.write( - """ -typedef struct { - const Icon* icon; - const char* path; -} IconPath; - -extern const IconPath ICON_PATHS[]; -extern const size_t ICON_PATHS_COUNT; -""" - ) - else: + if self.args.fw_bundle: + icons_h.write(ICONS_TEMPLATE_H_ICON_PATHS) + if self.args.add_include: icons_h.write("#include \n") icons_h.close() self.logger.debug("Done") diff --git a/scripts/check_unused_icons.py b/scripts/check_unused_icons.py new file mode 100755 index 000000000..0f7967db3 --- /dev/null +++ b/scripts/check_unused_icons.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +import pathlib + +root = pathlib.Path(__file__).parent / ".." +icons = root / "assets/icons" + + +def count_icon_usages(name: str): + count = 0 + name = name.encode() + # EXTREMELY wasteful, but who cares + for dir in ("applications", "furi", "lib", "targets"): + for filetype in (".c", ".cpp", ".h", ".fam"): + for file in (root / dir).glob(f"**/*{filetype}"): + try: + if name in file.read_bytes(): + count += 1 + except Exception: + print(f"Failed to read {file}") + return count + + +if __name__ == "__main__": + counts = {} + + for category in icons.iterdir(): + if not category.is_dir(): + continue + for icon in category.iterdir(): + if icon.is_dir() and (icon / "frame_rate").is_file(): + name = "A_" + icon.name.replace("-", "_") + elif icon.is_file() and icon.suffix == ".png": + name = "I_" + "_".join(icon.name.split(".")[:-1]).replace("-", "_") + else: + continue + counts[name[2:]] = count_icon_usages(name) + + for name, count in sorted(counts.items(), key=lambda x: x[1], reverse=True): + print(f"{name} used {count} times") diff --git a/scripts/fbt_tools/fbt_assets.py b/scripts/fbt_tools/fbt_assets.py index 012ff5329..b3e70ab05 100644 --- a/scripts/fbt_tools/fbt_assets.py +++ b/scripts/fbt_tools/fbt_assets.py @@ -181,7 +181,15 @@ def _proto_ver_generator(target, source, env): file.write("\n".join(version_file_data)) -def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons"): +def CompileIcons( + env, + target_dir, + source_dir, + *, + icon_bundle_name="assets_icons", + fw_bundle=False, + add_include=False, +): try: os.mkdir(str(source_dir)) except FileExistsError: @@ -191,6 +199,8 @@ def CompileIcons(env, target_dir, source_dir, *, icon_bundle_name="assets_icons" None, ICON_SRC_DIR=source_dir, ICON_FILE_NAME=icon_bundle_name, + ICON_FW_BUNDLE=int(fw_bundle), + ICON_ADD_INCLUDE=int(add_include), ) @@ -223,6 +233,10 @@ def generate(env): "${TARGET.dir}", "--filename", "${ICON_FILE_NAME}", + "--fw-bundle", + "${ICON_FW_BUNDLE}", + "--add-include", + "${ICON_ADD_INCLUDE}", ], ], "${ICONSCOMSTR}", diff --git a/scripts/fbt_tools/fbt_extapps.py b/scripts/fbt_tools/fbt_extapps.py index da5e272a8..26b1025d9 100644 --- a/scripts/fbt_tools/fbt_extapps.py +++ b/scripts/fbt_tools/fbt_extapps.py @@ -90,6 +90,7 @@ class AppBuilder: self.app_work_dir, self.app._appdir.Dir(self.app.fap_icon_assets), icon_bundle_name=f"{self.app.fap_icon_assets_symbol or self.app.appid }_icons", + add_include=True, ) self.app_env.Alias("_fap_icons", fap_icons) self.fw_env.Append(_APP_ICONS=[fap_icons]) diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index af8ab3f60..cd892e373 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -3919,12 +3919,12 @@ Variable,+,I_CC_LefthandedMode_16x16,const Icon, Variable,+,I_CC_Lock_16x16,const Icon, Variable,+,I_CC_Momentum_16x16,const Icon, Variable,+,I_CC_Settings_16x16,const Icon, -Variable,+,I_Certification1_103x56,const Icon, -Variable,+,I_Certification2_46x33,const Icon, -Variable,+,I_CertificationChina0_121x41,const Icon, -Variable,+,I_CertificationChina1_124x47,const Icon, -Variable,+,I_CertificationMexico_98x41,const Icon, -Variable,+,I_CertificationTaiwan_33x32,const Icon, +Variable,-,I_Certification1_103x56,const Icon, +Variable,-,I_Certification2_46x33,const Icon, +Variable,-,I_CertificationChina0_121x41,const Icon, +Variable,-,I_CertificationChina1_124x47,const Icon, +Variable,-,I_CertificationMexico_98x41,const Icon, +Variable,-,I_CertificationTaiwan_33x32,const Icon, Variable,+,I_Charging_lightning_9x10,const Icon, Variable,+,I_Charging_lightning_mask_9x10,const Icon, Variable,+,I_Circles_47x47,const Icon, @@ -3932,7 +3932,7 @@ Variable,+,I_Clock_18x18,const Icon, Variable,+,I_Connect_me_62x31,const Icon, Variable,+,I_Connected_62x31,const Icon, Variable,+,I_Cos_9x7,const Icon, -Variable,+,I_DFU_128x50,const Icon, +Variable,-,I_DFU_128x50,const Icon, Variable,+,I_DolphinDone_80x58,const Icon, Variable,+,I_DolphinMafia_119x62,const Icon, Variable,+,I_DolphinReadingSuccess_59x63,const Icon, @@ -3941,7 +3941,7 @@ Variable,+,I_DolphinSuccess_91x55,const Icon, Variable,+,I_DolphinWait_59x54,const Icon, Variable,+,I_Drive_112x35,const Icon, Variable,+,I_Dynamic_9x7,const Icon, -Variable,+,I_Erase_pin_128x64,const Icon, +Variable,-,I_Erase_pin_128x64,const Icon, Variable,+,I_Error_18x18,const Icon, Variable,+,I_Error_62x31,const Icon, Variable,+,I_EviSmile1_18x21,const Icon, @@ -3975,7 +3975,7 @@ Variable,+,I_Left_mouse_icon_9x9,const Icon, Variable,+,I_LoadingHourglass_24x24,const Icon, Variable,+,I_Lock_7x8,const Icon, Variable,+,I_Lockscreen,const Icon, -Variable,+,I_MFKey_qr_25x25,const Icon, +Variable,-,I_MFKey_qr_25x25,const Icon, Variable,+,I_MHz_25x11,const Icon, Variable,+,I_Modern_reader_18x34,const Icon, Variable,+,I_More_data_placeholder_5x7,const Icon, @@ -3990,11 +3990,8 @@ Variable,+,I_Percent_10x14,const Icon, Variable,+,I_Pin_arrow_up_7x9,const Icon, Variable,+,I_Pin_attention_dpad_29x29,const Icon, Variable,+,I_Pin_back_arrow_10x8,const Icon, -Variable,+,I_Pin_cell_13x13,const Icon, Variable,+,I_Pin_pointer_5x3,const Icon, Variable,+,I_Pin_star_7x7,const Icon, -Variable,+,I_Play_25x27,const Icon, -Variable,+,I_Play_hvr_25x27,const Icon, Variable,+,I_Pressed_Button_13x13,const Icon, Variable,+,I_Quest_7x8,const Icon, Variable,+,I_RFIDDolphinReceive_97x61,const Icon, @@ -4005,7 +4002,7 @@ Variable,+,I_Release_arrow_18x15,const Icon, Variable,+,I_Right_mouse_icon_9x9,const Icon, Variable,+,I_Rpc_active_7x8,const Icon, Variable,+,I_SDQuestion_35x43,const Icon, -Variable,+,I_SDcardFail_11x8,const Icon, +Variable,-,I_SDcardFail_11x8,const Icon, Variable,+,I_SDcardMounted_11x8,const Icon, Variable,+,I_Sats_6x9,const Icon, Variable,+,I_Scanning_123x52,const Icon, @@ -4018,15 +4015,15 @@ Variable,+,I_Temperature_16x16,const Icon, Variable,+,I_Unlock_7x8,const Icon, Variable,+,I_Unplug_bg_bottom_128x10,const Icon, Variable,+,I_Unplug_bg_top_128x14,const Icon, -Variable,+,I_Updating_32x40,const Icon, -Variable,+,I_Updating_Logo_62x15,const Icon, +Variable,-,I_Updating_32x40,const Icon, +Variable,-,I_Updating_Logo_62x15,const Icon, Variable,+,I_UsbTree_48x22,const Icon, Variable,+,I_Voldwn_6x6,const Icon, Variable,+,I_Voltage_16x16,const Icon, Variable,+,I_Volup_8x6,const Icon, Variable,+,I_WarningDolphinFlip_45x42,const Icon, Variable,+,I_WarningDolphin_45x42,const Icon, -Variable,+,I_Warning_30x23,const Icon, +Variable,-,I_Warning_30x23,const Icon, Variable,+,I_Weather_7x8,const Icon, Variable,+,I_arrow_nano_down,const Icon, Variable,+,I_arrow_nano_up,const Icon, @@ -4053,14 +4050,14 @@ Variable,+,I_dry_text_15x5,const Icon, Variable,+,I_eject_19x20,const Icon, Variable,+,I_eject_hover_19x20,const Icon, Variable,+,I_eject_text_19x5,const Icon, -Variable,+,I_err_01,const Icon, -Variable,+,I_err_02,const Icon, -Variable,+,I_err_03,const Icon, -Variable,+,I_err_04,const Icon, -Variable,+,I_err_05,const Icon, -Variable,+,I_err_06,const Icon, -Variable,+,I_err_07,const Icon, -Variable,+,I_err_09,const Icon, +Variable,-,I_err_01,const Icon, +Variable,-,I_err_02,const Icon, +Variable,-,I_err_03,const Icon, +Variable,-,I_err_04,const Icon, +Variable,-,I_err_05,const Icon, +Variable,-,I_err_06,const Icon, +Variable,-,I_err_07,const Icon, +Variable,-,I_err_09,const Icon, Variable,+,I_exit_19x20,const Icon, Variable,+,I_exit_hover_19x20,const Icon, Variable,+,I_exit_text_18x5,const Icon, @@ -4077,13 +4074,6 @@ Variable,+,I_floppydisk_10px,const Icon, Variable,+,I_green_19x20,const Icon, Variable,+,I_green_hover_19x20,const Icon, Variable,+,I_heat_30x51,const Icon, -Variable,+,I_hourglass0_24x24,const Icon, -Variable,+,I_hourglass1_24x24,const Icon, -Variable,+,I_hourglass2_24x24,const Icon, -Variable,+,I_hourglass3_24x24,const Icon, -Variable,+,I_hourglass4_24x24,const Icon, -Variable,+,I_hourglass5_24x24,const Icon, -Variable,+,I_hourglass6_24x24,const Icon, Variable,+,I_iButtonDolphinVerySuccess_92x55,const Icon, Variable,+,I_iButtonKey_49x44,const Icon, Variable,+,I_ibutt_10px,const Icon, @@ -4136,7 +4126,7 @@ Variable,+,I_power_text_24x5,const Icon, Variable,+,I_prev_19x20,const Icon, Variable,+,I_prev_hover_19x20,const Icon, Variable,+,I_prev_text_19x5,const Icon, -Variable,+,I_qr_benchmark_25x25,const Icon, +Variable,-,I_qr_benchmark_25x25,const Icon, Variable,+,I_red_19x20,const Icon, Variable,+,I_red_hover_19x20,const Icon, Variable,+,I_rotate_19x20,const Icon, diff --git a/targets/f7/target.json b/targets/f7/target.json index c5a65704a..810c76d95 100644 --- a/targets/f7/target.json +++ b/targets/f7/target.json @@ -35,7 +35,7 @@ "microtar", "usb_stm32", "infrared", - "assets", + "fwassets", "one_wire", "ibutton", "music_worker",