├── .eslintrc.cjs ├── .gitignore ├── .gitmodules ├── .prettierignore ├── LICENSE ├── README.md ├── archive ├── myamazfit-0.en.md └── myamazfit-0.ru.md ├── demo.png ├── index.html ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── files │ ├── app │ │ ├── game-2048-v0.3-by-zener79.elf │ │ ├── game-4letters-by-x27.elf │ │ ├── game-Breakout-by-PRO100KBAC.elf │ │ ├── game-Magic8BallRU-by-erekoze.elf │ │ ├── game-Minesweeper-by-x27.elf │ │ ├── game-PingPong-by-PRO100KBAC.elf │ │ ├── game-Snake-by-PRO100KBAC.elf │ │ ├── game-SokobanBIP-v1.1-by-000edu.elf │ │ ├── game-TRex-by-Yuukari.elf │ │ ├── game-TetrisBIP-v1.3-by-000edu.elf │ │ ├── game-boxpop-v1.1-by-x27.elf │ │ ├── game-fifteen-by-x27.elf │ │ ├── game-flappybird-v0.2.7-by-PRO100KBAC.elf │ │ ├── game-unblockme-by-x27.elf │ │ ├── hook-alarm-manager-by-MNVolkov.elf │ │ ├── hook-animated-menu.elf │ │ ├── hook-simpleDND-by-MNVolkov.elf │ │ ├── utility-BTNotes-v3.0-by-ngxson.elf │ │ ├── utility-BipCounter-v2.4-by-erekoze.elf │ │ ├── utility-GoHome-by-MikhailU.elf │ │ ├── utility-NotesBIPAqua-v1.1-by-000edu.elf │ │ ├── utility-NotesBIPPurple-v1.1-by-000edu.elf │ │ ├── utility-SafeBoxBIP-v1.1-by-000edu.elf │ │ ├── utility-calculator-by-MNVolkov.elf │ │ ├── utility-calendar-by-MNVolkov.elf │ │ ├── utility-flashlight-by-MNVolkov.elf │ │ ├── utility-gps-returner-by-x27.elf │ │ ├── utility-metronome-by-ngxson.elf │ │ ├── utility-music-control-by-MNVolkov.elf │ │ ├── utility-navigator-Marlen-Maksumov.elf │ │ ├── utility-vietnamese-calendar-by-ngxson.elf │ │ ├── watchface-abstract-by-ssp1971.elf │ │ ├── watchface-keanu-by-MNVolkov.elf │ │ └── watchface-mickey-by-usb.elf │ ├── font │ │ ├── BOLD_V6.2_not_latin.ft │ │ ├── BOLD_v4q_newsmiles.ft │ │ └── Vietnamese_Emoji_v5.3.ft │ ├── fw │ │ ├── BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.fw │ │ ├── BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.fw │ │ └── BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.fw │ ├── libbip │ │ ├── BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.bin │ │ ├── BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.bin │ │ └── BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.bin │ └── res │ │ ├── BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.res │ │ ├── BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.res │ │ └── BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.res └── logo.png ├── scripts └── build-files-directory.cjs ├── src ├── App.tsx ├── bootstrap.min.css ├── components │ ├── About.tsx │ ├── FWCredits.tsx │ ├── FileList.tsx │ ├── ResBuilder │ │ ├── AppPicker.tsx │ │ ├── ResEditor.tsx │ │ ├── ResUtils.ts │ │ └── index.tsx │ └── Utils.ts ├── data │ └── files.json ├── index.css ├── main.tsx └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:react-hooks/recommended', 8 | ], 9 | ignorePatterns: ['dist', '.eslintrc.cjs'], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['react-refresh'], 12 | rules: { 13 | 'react-refresh/only-export-components': [ 14 | 'warn', 15 | { allowConstantExport: true }, 16 | ], 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "res-tools"] 2 | path = res-tools 3 | url = https://github.com/ngxson/amazfit-bip-tools-ts.git 4 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/.git 2 | **/.svn 3 | **/.hg 4 | **/node_modules 5 | 6 | /dist 7 | /public 8 | *.json 9 | bootstrap.min.css 10 | *.md 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Xuan Son Nguyen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Amazfit Bip Firmware Tools 2 | 3 | Tools for making .res file for **Amazfit Bip** smartwatch. 4 | 5 | It is completely online, no need to download any additional tools to your computer. 6 | 7 | Website: [amazfitbip.ngxson.com](https://amazfitbip.ngxson.com) 8 | 9 | ![demo](./demo.png) 10 | 11 | ## Introduction 12 | 13 | NOTE: Below is a conversation between me and ChatGPT 14 | 15 | > What is Amazfit Bip? What is BipOS ? 16 | 17 | Yes, I can provide information about both Amazfit Bip and BipOS. 18 | 19 | **Amazfit Bip** 20 | 21 | The Amazfit Bip is a popular smartwatch developed by Huami, a subsidiary of Xiaomi. It's known for its long battery life, affordability, and basic but functional feature set. Here are some key features and characteristics of the Amazfit Bip: 22 | 23 | - **Display**: 1.28-inch transflective color touchscreen, which is always on and easily readable in sunlight. 24 | - **Battery Life**: Up to 30-45 days on a single charge, depending on usage. 25 | - **Sensors**: Includes GPS, heart rate monitor, accelerometer, and barometer. 26 | - **Connectivity**: Bluetooth 4.0 for connecting with smartphones. 27 | - **Water Resistance**: Rated at IP68, meaning it's dust-tight and can withstand submersion in water up to 1.5 meters for 30 minutes. 28 | - **Notifications**: Can receive notifications for calls, messages, emails, and other apps when connected to a smartphone. 29 | - **Fitness Tracking**: Supports tracking for activities such as running, walking, cycling, and more. 30 | 31 | **BipOS** 32 | 33 | BipOS is a custom operating system designed for the Amazfit Bip smartwatch. It allows users to enhance the functionality of their Amazfit Bip devices by installing additional features and apps not available in the stock firmware. Here are some aspects of BipOS: 34 | 35 | - **Customization**: Provides a high level of customization for the watch face and other UI elements. 36 | - **Extended Features**: Includes additional applications and tools such as games, calculators, and more advanced fitness tracking features. 37 | - **Community-Driven**: BipOS is often developed and maintained by a community of enthusiasts, offering a variety of mods and updates based on user feedback. 38 | - **Installation**: Typically, installing BipOS requires some technical knowledge and the willingness to tinker with the device’s firmware. 39 | 40 | The combination of Amazfit Bip's hardware and BipOS's customizable software can offer users a more personalized and feature-rich smartwatch experience. 41 | 42 | > What is amazfitbip.ngxson.com? 43 | 44 | The website "amazfitbip.ngxson.com" is an active resource that provides tools and firmware for the Amazfit Bip smartwatch. It includes various firmware files, tools for flashing the firmware, and additional resources for enhancing the smartwatch's functionality. 45 | 46 | Ngxson, the developer behind this website, also maintains a GitHub repository with several projects related to the Amazfit Bip. These projects include custom applications for BipOS, such as a metronome and beat tap app, showcasing the versatility of the smartwatch when paired with custom firmware. 47 | 48 | For more information or to explore the tools and resources provided, you can visit the [Amazfit Bip Firmware Tools site](https://amazfitbip.ngxson.com) and Ngxson's [GitHub profile](https://github.com/ngxson). 49 | -------------------------------------------------------------------------------- /archive/myamazfit-0.en.md: -------------------------------------------------------------------------------- 1 | --- 2 | source: https://web.archive.org/web/20220517211541/https://myamazfit.ru/threads/bip-prilozhenija-dlja-bipos-elf.1174/ 3 | --- 4 | 5 | > The article below is archived from "myamazfit.ru" 6 | 7 | ## 1. Calculator 8 | The "Calculator" app allows you to perform basic arithmetic operations + - * /. Deleting the last digit entered, resetting, and obtaining the answer is done by pressing the respective areas on the display, marked with the labels C = <-. Pressing the side button resets the calculator, and pressing it again exits the app. A long press on the side button also exits the app. 9 | 10 | ## 2. Calendar 11 | The "Calendar" app displays the calendar for the current month and any selected month of any year. The calendar works from the year 1600 to 3000. The day of the week calculation algorithm works for any date in the Gregorian calendar. When launched, the current month is displayed, and the current day is highlighted. The names of the months at the top of the screen are fully spelled out, unlike previous versions. You can select another month and year: swipe up/down to switch the month, and use the arrows to switch the year. Tapping the name of the month returns to the current date. You can choose from several color schemes, with the choice saved in non-volatile memory. 12 | 13 | Source code: https://github.com/MNVolkov/Calend 14 | 15 | ## 3. Alarm Editor 16 | The "Alarm Editor" app is available from the alarm settings menu. You can change the time of a selected alarm, set repetition by weekdays, or choose a one-time mode. Repetition is selected on a screen accessible by swiping left. To select the one-time mode, uncheck all the boxes. For convenience, you can set the current time by tapping the alarm icon on the time setting screen. Synchronization with MiFit only affects the on/off status (as before), without changing the time in MiFit. However, you can still set an alarm in MiFit, and it will be loaded into the watch. Alarm data on the watch is always up-to-date. Tapping the "alarm" icon sets the current time. Currently, you can only edit existing alarms, not add or delete them. 17 | 18 | For BipOS 0.5.2 19 | 20 | ## 4. Flashlight 21 | The simple "Flashlight" app is designed to illuminate things using the screen's backlight LEDs. When launched, the flashlight immediately turns on the backlight to full and fills the screen with white light. You can turn the flashlight on and off by tapping the screen. Exit the app as usual with a right swipe or the side button. 22 | 23 | Source code: https://github.com/MNVolkov/Flashlight 24 | 25 | --- 26 | 27 | ### Apps for BipOS (elf) 28 | 29 | In this topic, I suggest publishing apps for BipOS, with descriptions, screenshots, etc. Initially, we can discuss the apps here, and when the number of apps grows, we can consider moving to a different platform. 30 | 31 | **Topics related to BipOS:** 32 | - Firmware - Bip | MNVolkov BipOS 33 | - Application development for BipOS and installation instructions: Bip | BipOS Application Development (SDK) 34 | - Resource packer for adding elf-applications to the resource file. 35 | - LikeApp - Android app for installing elf-apps on the watch. 36 | 37 | **List of Apps:** 38 | 1. **Calculator** by @MNVolkov 39 | 2. **Calendar** by @MNVolkov 40 | 3. **Alarm Editor** by @MNVolkov 41 | 4. **Flashlight** by @MNVolkov 42 | 5. **Fitness Timer** by @AlexJey 43 | 6. **Music** by @MNVolkov 44 | - Mod with large buttons by @MNVolkov @trace 45 | - Mod with large buttons + ClockDateMod by @MNVolkov @trace @ugers 46 | - Mod with large buttons + StatusBar by @MNVolkov @trace @ugers 47 | 7. **Notepad** by @PRO100KBAC 48 | 8. **Heart Rate Chart (HR Chart)** by @fredlak 49 | 9. **Work Schedule (2/2, 1/3)** by @ugers 50 | 10. **SafeBox (for storing passwords, PIN codes)** by @000edu 51 | 11. **NotesBIP (Notes editor)** by @000edu 52 | 12. **Tap Counter (BipCounter)** by @erekoze @ugers 53 | - Tap Counter (BipCounter) + StatusBar by @erekoze @ugers 54 | 13. **Pulse Monitoring** by @Sanya pilot 55 | 14. **BipTask - interaction of the watch with the phone via Tasker** by @Yuukari 56 | 15. **GPS Returner** by @x27 57 | 16. **Bip Thermometer** by @erekoze 58 | 17. **simpleDND replacing the standard DND screen** by @MNVolkov 59 | 18. **Metronome** by @thichthat 60 | 19. **ExtDND DND screen with extended functions** by @thichthat 61 | 20. **BTNotes 3.0 Notes sent from the phone** by @thichthat 62 | 21. **Go Home - simplified GPS Returner analog using the compass** by @MikhailU 63 | 22. **Stopwatch** - stopwatch app with background time counting function by @MNVolkov 64 | 23. **WorldClock - world clocks** by @Comga.89 65 | 24. **WordsLearner - app for memorizing words** by @kvolodin 66 | 67 | **List of Games:** 68 | 1. **Tetris (version without vibration: NoVibration)** by @000edu 69 | 2. **FlappyBird** by @PRO100KBAC 70 | 3. **2048** by @zener79 71 | 4. **Sokoban (version without vibration: NoVibration)** by @000edu 72 | 5. **Ping-Pong** by @PRO100KBAC 73 | 6. **Breakout** by @PRO100KBAC 74 | 7. **Snake** by @PRO100KBAC 75 | 8. **Magic 8 Ball** by @erekoze 76 | 9. **FreeBip BoxPop** by @x27 77 | 10. **4 Letters** by @x27 78 | 11. **Minesweeper** by @x27 79 | 12. **Fifteen** by @x27 80 | 13. **Unblockme** by @x27 81 | 14. **Dinosaur (T-Rex)** by @Yuukari 82 | 83 | **List of Animations:** 84 | 1. **Keanu Animation (Cyberpunk 2077)** by @MNVolkov 85 | 2. **Steve WF** by @PRO100KBAC 86 | 3. **Mickey Mouse** by @usb 87 | 4. **Abstract** by @ssp1971 88 | 5. **Main menu animation in Bip 2 style** by @MNVolkov 89 | 90 | **Demo versions and apps for developers:** 91 | 1. **Random number generator demo** by @MNVolkov 92 | 2. **Own resource usage demo** by @MNVolkov 93 | 3. **Pulse Demo** by @MNVolkov 94 | 4. **BipSimulator (testing apps on PC)** by @en_rov 95 | 5. **BipUI Button Demo** by @en_rov 96 | 6. **BipUI Layers Demo** by @en_rov 97 | 7. **Bluetooth command testing** by @MNVolkov 98 | 8. **Lucky7 (random number generation from 1 to 7)** by @erekoze 99 | 9. **Navigator Demo** by @MNVolkov 100 | 10. (Please log in or register to view hidden text.) 101 | 11. **BipStatusBarLibrary (status bar library for apps)** by @ugers 102 | 12. **FastUI 1.0 beta Library for creating custom UI in apps** by @Yuukari 103 | 13. **Barcode, QR code generator (you will have to compile the app yourself)** by @kvolodin 104 | 105 | I hope this helps with your work on BipOS and the Amazfit Bip! If you have any further questions or need additional assistance, feel free to ask. 106 | -------------------------------------------------------------------------------- /archive/myamazfit-0.ru.md: -------------------------------------------------------------------------------- 1 | --- 2 | source: https://web.archive.org/web/20220517211541/https://myamazfit.ru/threads/bip-prilozhenija-dlja-bipos-elf.1174/ 3 | --- 4 | 5 | > The article below is archived from "myamazfit.ru" 6 | 7 | ## 1. Калькулятор 8 | Приложение "Калькулятор" позволяет выполнять основные арифметические операции + - * / . Удаление последней набранной цифры, сброс и получение ответа вызывается нажатием на соответствующих областях табло, обозначенных надписями C = <-. При нажатии боковой кнопки происходит сброс, при повторном выход из приложения. Долгое нажатие боковой кнопки приводит к выходу из приложения. 9 | 10 | ## 2. Календарь 11 | Приложение "Календарь" отображает календарь как на текущий месяц, так и на любой выбранный месяц любого года. Диапазон работы календаря от 1600 до 3000 года. Алгоритм вычисления дня недели работает для любой даты григорианского календаря. При запуске отображается текущий месяц, текущий день выделен цветом. Названия месяцев в верхней части экрана приведены полностью, в отличие от предыдущих версий. Возможность выбора другого месяца и года: свайп вверх/вниз для переключения месяца, стрелками переключение года. При нажатии на наименование месяца возврат к текущей дате. Возможность выбора одной из нескольких цветовых схем, с запоминанием выбора в энергонезависимой памяти. 12 | 13 | 14 | ## 3. Редактор будильников 15 | Приложение "Редактор будильников" доступно из меню установки будильников. Доступно изменение времени выбранного будильника, установка повторения по дням недели, либо выбор однократного режима. Выбор повторения осуществляется на экране доступном свайпом влево. Для выбора однократного режима необходимо снять все галочки. Для удобства можно установить текущее время нажатием на значок будильника на экране установки времени. Синхронизация с MiFit происходит только состояния вкл/выкл (как раньше), при этом время в MiFit не меняется. Однако можно по-прежнему установить будильник в MiFit и он загрузится в часы. Данные будильника в часах отображаются всегда актуальные. Нажатием значка "будильник" можно установить текущее время. Добавлять или удалять будильники пока нельзя, только редактировать существующие. 16 | 17 | Для BipOS 0.5.2 18 | 19 | ## 4. Фонарик 20 | Простое приложение "Фонарик" предназначено для освещения чего-либо светодиодами подсветки экрана. При запуске Фонарика сразу происходит включение подсветки на полную и заливка экрана белым цветом. Фонарик можно отключать и включать нажатием на экран. Выход из приложения как обычно - свайпом вправо или боковой кнопкой. 21 | 22 | --- 23 | 24 | Приложения для BipOS (elf)​ 25 | 26 | Предлагаю в данной теме публиковать приложения для BipOS, с описаниями, скриншотами и т.д. Обсуждение приложений для начала можно будет вести так же тут, когда количество приложений вырастет подумаем о переезде. 27 | 28 | Тема по BipsOS: Прошивка - Bip | MNVolkov BipOS 29 | Тема о разработке приложений для BipOS и инструкция по установке: Bip | Разработка приложений для BipOS ( SDK ) 30 | Архиватор ресурсов для добавления elf-приложений в файл ресурсов. 31 | LikeApp - приложение на Android для установки elf-приложений в часы. 32 | 33 | Список приложений: 34 | 1. Калькулятор Автор: @MNVolkov 35 | 2. Календарь Автор: @MNVolkov 36 | 3. Редактор будильников Автор: @MNVolkov 37 | 4. Фонарик Автор: @MNVolkov 38 | 5. Фитнес-таймер Автор: @AlexJey 39 | 6. Музыка Автор: @MNVolkov 40 | > мод с большими кнопками Автор: @MNVolkov @trace​ 41 | > мод с большими кнопками + ClockDateMod Автор: @MNVolkov @trace @ugers​ 42 | > мод с большими кнопками + StatusBar Автор: @MNVolkov @trace @ugers​ 43 | 7. Notepad Автор: @PRO100KBAC 44 | 8. График сердечного ритма (HR Chart) Автор: @fredlak 45 | 9. График работы (2/2, 1/3) Автор: @ugers 46 | 10. SafeBox (для сохранения паролей, PIN-кодов) Автор: @000edu 47 | 11. NotesBIP (Редактор заметок) Автор: @000edu 48 | 12. Счетчик нажатий (BipCounter) Автор: @erekoze @ugers 49 | > Счетчик нажатий (BipCounter) + StatusBar Автор: @erekoze @ugers​ 50 | 13. Мониторинг пульса Автор: @Sanya pilot 51 | 14. BipTask - взаимодействие часов с телефоном через Tasker Автор: @Yuukari 52 | 15. GPS Returner Автор: @x27 53 | 16. Bip Термометр Автор: @erekoze 54 | 17. simpleDND замена стандартного экрана DND Автор: @MNVolkov 55 | 18. Metronome (Метроном) Автор: @thichthat 56 | 19. ExtDND Экран DND с расширенными функциями. Автор: @thichthat 57 | 20. BTNotes 3.0 Заметки, отправленные с телефона. Автор: @thichthat 58 | 21. Go Home - упрощенный аналог GPS Returner с использованием компаса. Автор: @MikhailU 59 | 22. Секундомер ⏱ - приложение секундомер с функцией фонового отсчета времени. Автор: @MNVolkov 60 | 23. WorldClock - мировые часы. Автор: @Comga.89 61 | 24. WordsLearner - приложение для запоминания слов. Автор: @kvolodin 62 | 63 | Список игр: 64 | 1. Тетрис (версия без вибрации: NoVibration) Автор: @000edu 65 | 2. FlappyBird Автор: @PRO100KBAC 66 | 3. 2048 Автор: @zener79 67 | 4. Sokoban (версия без вибрации: NoVibration) Автор: @000edu 68 | 5. Ping-Pong Автор: @PRO100KBAC 69 | 6. Breakout Автор: @PRO100KBAC 70 | 7. Snake Автор: @PRO100KBAC 71 | 8. Магический шар 8 Автор: @erekoze 72 | 9. FreeBip BoxPop Автор: @x27 73 | 10. 4 буквы Автор: @x27 74 | 11. Сапёр Автор: @x27 75 | 12. Пятнадцать Автор: @x27 76 | 13. Unblockme Автор: @x27 77 | 14. Динозаврик (T-Rex) Автор: @Yuukari 78 | 79 | Список анимации: 80 | 1. Анимация Keanu (Cyberpunk 2077) Автор: @MNVolkov 81 | 2. Steve WF Автор: @PRO100KBAC 82 | 3. Mickey mouse Автор: @usb 83 | 4. Abstract Автор: @ssp1971 84 | 5. Анимация главного меню в стиле Bip 2 Автор: @MNVolkov 85 | 86 | Демо версии и приложения для разработчиков: 87 | 1. Демонстрация генератора случайных чисел Автор: @MNVolkov 88 | 2. Демонстрация использования "собственных" ресурсов Автор: @MNVolkov 89 | 3. Пульс Демо Автор: @MNVolkov 90 | 4. BipSimulator (тестирование приложений на ПК) Автор: @en_rov 91 | 5. BipUI Демо кнопок Автор: @en_rov 92 | 6. BipUI Демо слои Автор: @en_rov 93 | 7. Тестирование bluetooth команд Автор: @MNVolkov 94 | 8. Lucky7 (генерация рандомных чисел от 1 до 7) Автор: @erekoze 95 | 9. Навигатор Демо Автор: @MNVolkov 96 | 10. (Пожалуйста войдите или зарегистрируйтесь для просмотра скрытого текста.) 97 | 11. BipStatusBarLibrary (библиотека статусбара для приложений) Автор: @ugers 98 | 12. FastUI 1.0 beta Библиотека для создания пользовательского интерфейса в приложениях. Автор: @Yuukari 99 | 13. Генератор штрих-кодов, QR-кодов (собирать приложение придется самостоятельно) Автор: @kvolodin 100 | -------------------------------------------------------------------------------- /demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/demo.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Amazfit Bip Firmware Tools 8 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hobby-amazfit-bip-web", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "predev": "npm run build:files-directory", 8 | "dev": "vite", 9 | "prebuild": "npm run build:files-directory", 10 | "build": "tsc && vite build", 11 | "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", 12 | "build:files-directory": "node scripts/build-files-directory.cjs", 13 | "format": "prettier --write ." 14 | }, 15 | "dependencies": { 16 | "amazfit-bip-tools-ts": "file:res-tools", 17 | "axios": "^1.7.2", 18 | "file-saver": "^2.0.5", 19 | "prettier": "^3.3.2", 20 | "react": "^18.2.0", 21 | "react-bootstrap": "^2.10.2", 22 | "react-dom": "^18.2.0", 23 | "react-router-dom": "^5.3.4" 24 | }, 25 | "devDependencies": { 26 | "@types/file-saver": "^2.0.7", 27 | "@types/react": "^18.2.66", 28 | "@types/react-dom": "^18.2.22", 29 | "@types/react-router-dom": "^5.3.3", 30 | "@typescript-eslint/eslint-plugin": "^7.2.0", 31 | "@typescript-eslint/parser": "^7.2.0", 32 | "@vitejs/plugin-react": "^4.2.1", 33 | "eslint": "^8.57.0", 34 | "eslint-plugin-react-hooks": "^4.6.0", 35 | "eslint-plugin-react-refresh": "^0.4.6", 36 | "typescript": "^5.2.2", 37 | "vite": "^5.2.0" 38 | }, 39 | "prettier": { 40 | "trailingComma": "es5", 41 | "tabWidth": 2, 42 | "semi": true, 43 | "singleQuote": true, 44 | "bracketSameLine": false 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/favicon.ico -------------------------------------------------------------------------------- /public/files/app/game-2048-v0.3-by-zener79.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-2048-v0.3-by-zener79.elf -------------------------------------------------------------------------------- /public/files/app/game-4letters-by-x27.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-4letters-by-x27.elf -------------------------------------------------------------------------------- /public/files/app/game-Breakout-by-PRO100KBAC.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-Breakout-by-PRO100KBAC.elf -------------------------------------------------------------------------------- /public/files/app/game-Magic8BallRU-by-erekoze.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-Magic8BallRU-by-erekoze.elf -------------------------------------------------------------------------------- /public/files/app/game-Minesweeper-by-x27.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-Minesweeper-by-x27.elf -------------------------------------------------------------------------------- /public/files/app/game-PingPong-by-PRO100KBAC.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-PingPong-by-PRO100KBAC.elf -------------------------------------------------------------------------------- /public/files/app/game-Snake-by-PRO100KBAC.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-Snake-by-PRO100KBAC.elf -------------------------------------------------------------------------------- /public/files/app/game-SokobanBIP-v1.1-by-000edu.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-SokobanBIP-v1.1-by-000edu.elf -------------------------------------------------------------------------------- /public/files/app/game-TRex-by-Yuukari.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-TRex-by-Yuukari.elf -------------------------------------------------------------------------------- /public/files/app/game-TetrisBIP-v1.3-by-000edu.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-TetrisBIP-v1.3-by-000edu.elf -------------------------------------------------------------------------------- /public/files/app/game-boxpop-v1.1-by-x27.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-boxpop-v1.1-by-x27.elf -------------------------------------------------------------------------------- /public/files/app/game-fifteen-by-x27.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-fifteen-by-x27.elf -------------------------------------------------------------------------------- /public/files/app/game-flappybird-v0.2.7-by-PRO100KBAC.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-flappybird-v0.2.7-by-PRO100KBAC.elf -------------------------------------------------------------------------------- /public/files/app/game-unblockme-by-x27.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/game-unblockme-by-x27.elf -------------------------------------------------------------------------------- /public/files/app/hook-alarm-manager-by-MNVolkov.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/hook-alarm-manager-by-MNVolkov.elf -------------------------------------------------------------------------------- /public/files/app/hook-animated-menu.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/hook-animated-menu.elf -------------------------------------------------------------------------------- /public/files/app/hook-simpleDND-by-MNVolkov.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/hook-simpleDND-by-MNVolkov.elf -------------------------------------------------------------------------------- /public/files/app/utility-BTNotes-v3.0-by-ngxson.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-BTNotes-v3.0-by-ngxson.elf -------------------------------------------------------------------------------- /public/files/app/utility-BipCounter-v2.4-by-erekoze.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-BipCounter-v2.4-by-erekoze.elf -------------------------------------------------------------------------------- /public/files/app/utility-GoHome-by-MikhailU.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-GoHome-by-MikhailU.elf -------------------------------------------------------------------------------- /public/files/app/utility-NotesBIPAqua-v1.1-by-000edu.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-NotesBIPAqua-v1.1-by-000edu.elf -------------------------------------------------------------------------------- /public/files/app/utility-NotesBIPPurple-v1.1-by-000edu.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-NotesBIPPurple-v1.1-by-000edu.elf -------------------------------------------------------------------------------- /public/files/app/utility-SafeBoxBIP-v1.1-by-000edu.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-SafeBoxBIP-v1.1-by-000edu.elf -------------------------------------------------------------------------------- /public/files/app/utility-calculator-by-MNVolkov.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-calculator-by-MNVolkov.elf -------------------------------------------------------------------------------- /public/files/app/utility-calendar-by-MNVolkov.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-calendar-by-MNVolkov.elf -------------------------------------------------------------------------------- /public/files/app/utility-flashlight-by-MNVolkov.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-flashlight-by-MNVolkov.elf -------------------------------------------------------------------------------- /public/files/app/utility-gps-returner-by-x27.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-gps-returner-by-x27.elf -------------------------------------------------------------------------------- /public/files/app/utility-metronome-by-ngxson.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-metronome-by-ngxson.elf -------------------------------------------------------------------------------- /public/files/app/utility-music-control-by-MNVolkov.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-music-control-by-MNVolkov.elf -------------------------------------------------------------------------------- /public/files/app/utility-navigator-Marlen-Maksumov.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-navigator-Marlen-Maksumov.elf -------------------------------------------------------------------------------- /public/files/app/utility-vietnamese-calendar-by-ngxson.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/utility-vietnamese-calendar-by-ngxson.elf -------------------------------------------------------------------------------- /public/files/app/watchface-abstract-by-ssp1971.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/watchface-abstract-by-ssp1971.elf -------------------------------------------------------------------------------- /public/files/app/watchface-keanu-by-MNVolkov.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/watchface-keanu-by-MNVolkov.elf -------------------------------------------------------------------------------- /public/files/app/watchface-mickey-by-usb.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/app/watchface-mickey-by-usb.elf -------------------------------------------------------------------------------- /public/files/font/BOLD_V6.2_not_latin.ft: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/font/BOLD_V6.2_not_latin.ft -------------------------------------------------------------------------------- /public/files/font/BOLD_v4q_newsmiles.ft: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/font/BOLD_v4q_newsmiles.ft -------------------------------------------------------------------------------- /public/files/font/Vietnamese_Emoji_v5.3.ft: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/font/Vietnamese_Emoji_v5.3.ft -------------------------------------------------------------------------------- /public/files/fw/BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.fw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/fw/BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.fw -------------------------------------------------------------------------------- /public/files/fw/BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.fw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/fw/BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.fw -------------------------------------------------------------------------------- /public/files/fw/BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.fw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/fw/BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.fw -------------------------------------------------------------------------------- /public/files/libbip/BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/libbip/BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.bin -------------------------------------------------------------------------------- /public/files/libbip/BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/libbip/BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.bin -------------------------------------------------------------------------------- /public/files/libbip/BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/libbip/BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.bin -------------------------------------------------------------------------------- /public/files/res/BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/res/BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.res -------------------------------------------------------------------------------- /public/files/res/BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/res/BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.res -------------------------------------------------------------------------------- /public/files/res/BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.res: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/files/res/BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.res -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ngxson/amazfit-bip-web/74ee2ba142f88d1a7d08babe61e8ff372b431661/public/logo.png -------------------------------------------------------------------------------- /scripts/build-files-directory.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const DIR_FW = '../public/files/fw'; 5 | const DIR_RES = '../public/files/res'; 6 | const DIR_APP = '../public/files/app'; 7 | const DIR_FONT = '../public/files/font'; 8 | const DIR_LIBBIP = '../public/files/libbip'; 9 | const OUTPUT_DIR = '../src/data/files.json'; 10 | 11 | function run() { 12 | processDir(DIR_FW, 'fw'); 13 | processDir(DIR_RES, 'res'); 14 | processDir(DIR_APP, 'app'); 15 | processDir(DIR_FONT, 'font'); 16 | processDir(DIR_LIBBIP, 'libbip'); 17 | const newContent = JSON.stringify(content, null, 2); 18 | fs.writeFileSync(path.join(__dirname, OUTPUT_DIR), newContent); 19 | } 20 | 21 | const content = JSON.parse( 22 | fs.readFileSync(path.join(__dirname, OUTPUT_DIR)).toString() 23 | ); 24 | const getFileList = (relativePath) => { 25 | const dir = path.join(__dirname, relativePath); 26 | return fs.readdirSync(dir).map((filename) => ({ 27 | filename, 28 | size: fs.statSync(path.join(dir, filename)).size, 29 | })); 30 | }; 31 | 32 | const processDir = (relativePath, label) => { 33 | if (!content[label]) content[label] = {}; 34 | const files = getFileList(relativePath); 35 | for (const { filename, size } of files) { 36 | content[label][filename] = { 37 | ...content[label][filename], 38 | size, 39 | }; 40 | } 41 | content[label] = sortObjectKeys(content[label]); 42 | }; 43 | 44 | const sortObjectKeys = (o) => 45 | Object.keys(o) 46 | .sort() 47 | .reduce((obj, key) => { 48 | obj[key] = o[key]; 49 | return obj; 50 | }, {}); 51 | 52 | run(); 53 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { HashRouter, Route } from 'react-router-dom'; 3 | import ResBuilder from './components/ResBuilder'; 4 | import FileList from './components/FileList'; 5 | import About from './components/About'; 6 | import FWCredits from './components/FWCredits'; 7 | import { Container, Navbar, Row } from 'react-bootstrap'; 8 | 9 | class App extends React.Component { 10 | ResBuilder = () => { 11 | return ; 12 | }; 13 | 14 | Firmware = () => { 15 | return ( 16 | 17 | 18 | 19 | ); 20 | }; 21 | 22 | Font = () => { 23 | return ; 24 | }; 25 | 26 | About = () => { 27 | return ; 28 | }; 29 | 30 | render() { 31 | return ( 32 | <> 33 | 34 | 35 | 36 | Amazfit Bip 37 | 38 | 49 | 87 | 88 | 89 | 90 | 91 |
92 |
93 |
94 |
95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 |
104 | 105 | ); 106 | } 107 | } 108 | 109 | export default App; 110 | -------------------------------------------------------------------------------- /src/components/About.tsx: -------------------------------------------------------------------------------- 1 | function FileList() { 2 | return ( 3 | <> 4 |
5 |

About this website

6 |

Online .res builder for Amazfit Bip

7 |
8 |
9 | Application made by{' '} 10 | 11 | ngxson.com 12 | 13 |
14 | {/* eslint-disable-next-line */} 15 | Contact me via my email:{' '} 16 | 17 | { 18 | '\u0063\u006f\u006e\u0074\u0061\u0063\u0074\u0040\u006e\u0067\u0078\u0073\u006f\u006e\u002e\u0063\u006f\u006d' 19 | } 20 | 21 |
22 |
23 | Thanks to: 24 |
- MNVolkov for his work 25 | on BipOS 26 |
27 |
28 |
29 |
30 | THIS WEBSITE IS OPEN-SOURCE:{' '} 31 | 32 | ngxson/hobby-amazfit-bip-web 33 | 34 |
35 |
36 | 37 | ); 38 | } 39 | 40 | export default FileList; 41 | -------------------------------------------------------------------------------- /src/components/FWCredits.tsx: -------------------------------------------------------------------------------- 1 | export default function FWCredits() { 2 | return ( 3 | <> 4 |
5 |
6 | Thanks to: 7 |
- 8 | Mixann 9 | {' '} 10 | for 1.1.5.36 FW 11 |
12 | - Taha Nafis for b7 1.1.2.05 FW 13 |
14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /src/components/FileList.tsx: -------------------------------------------------------------------------------- 1 | import files from '../data/files.json'; 2 | import { ResDataType } from './Utils'; 3 | 4 | function FileList({ 5 | type, 6 | title, 7 | children, 8 | }: { 9 | type: ResDataType; 10 | title: string; 11 | children?: any; 12 | }) { 13 | return ( 14 | <> 15 |
16 |

{title}

17 |

Select a file to download:

18 |
19 |
20 |
    21 | {Object.keys(files[type]).map((filename) => ( 22 |
  • 23 | {filename} 24 |
  • 25 | ))} 26 |
27 |
28 |
29 | {children} 30 |
31 | 32 | ); 33 | } 34 | 35 | export default FileList; 36 | -------------------------------------------------------------------------------- /src/components/ResBuilder/AppPicker.tsx: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { useEffect, useState } from 'react'; 3 | import files from '../../data/files.json'; 4 | import { 5 | getELFSize, 6 | getELFMetadata, 7 | AppName, 8 | downloadArrayBuffer, 9 | } from '../Utils'; 10 | import { ResAsset } from 'amazfit-bip-tools-ts'; 11 | import { Button, Col, OverlayTrigger, Spinner, Tooltip } from 'react-bootstrap'; 12 | import { 13 | ResFileWrapped, 14 | ResWrappedName, 15 | getResByName, 16 | loadAllRes, 17 | } from './ResUtils'; 18 | 19 | async function getFile(url: string) { 20 | const { data } = await axios.get(url, { 21 | responseType: 'arraybuffer', 22 | }); 23 | const buf = new Uint8Array(data as ArrayBuffer); 24 | return buf; 25 | } 26 | 27 | const STORAGE_KEY_APPS = 'ngxson_apps'; 28 | const STORAGE_KEY_RES = 'ngxson_res'; 29 | const DEFAULT_APPS: AppName[] = [ 30 | 'hook-alarm-manager-by-MNVolkov.elf', 31 | 'utility-calendar-by-MNVolkov.elf', 32 | 'utility-calculator-by-MNVolkov.elf', 33 | 'utility-flashlight-by-MNVolkov.elf', 34 | ]; 35 | const POSSIBLE_RES = [...Object.keys(files.res), 'custom']; 36 | 37 | export default function AppPicker({ 38 | onChangeViewToEdit, 39 | }: { 40 | onChangeViewToEdit(): void; 41 | }) { 42 | const [loading, setLoading] = useState(true); 43 | const [resName, setResName] = useState(null); 44 | const [resFile, setResFile] = useState(null); 45 | const [apps, setApps] = useState(DEFAULT_APPS); 46 | 47 | // load saved data 48 | useEffect(() => { 49 | (async () => { 50 | await loadAllRes(); 51 | const savedApps = JSON.parse( 52 | localStorage.getItem(STORAGE_KEY_APPS) || 'null' 53 | ); 54 | if (savedApps) { 55 | setApps(savedApps.filter((a: string) => !!(files.app as any)[a])); 56 | } 57 | const savedRes = JSON.parse( 58 | localStorage.getItem(STORAGE_KEY_RES) || 'null' 59 | ); 60 | if (savedRes) { 61 | setResName(savedRes); 62 | } 63 | setLoading(false); 64 | })(); 65 | }, []); 66 | 67 | // reload the actual file when resName is changed 68 | useEffect(() => { 69 | if (!resName) { 70 | setResFile(null); 71 | return; 72 | } 73 | (async () => { 74 | setLoading(true); 75 | setResFile((await getResByName(resName as any)) ?? null); 76 | setLoading(false); 77 | })(); 78 | }, [resName]); 79 | 80 | // save app data to localStorage whenever there is change 81 | useEffect(() => { 82 | if (resName) { 83 | localStorage.setItem(STORAGE_KEY_RES, JSON.stringify(resName)); 84 | } 85 | localStorage.setItem(STORAGE_KEY_APPS, JSON.stringify(apps)); 86 | }, [resName, apps]); 87 | 88 | const addApp = (appName: AppName) => { 89 | setApps((apps) => [...apps, appName]); 90 | }; 91 | 92 | const moveApp = (direction: 'up' | 'down', i: number) => { 93 | setApps((oldApps) => { 94 | const apps = [...oldApps]; 95 | if (direction === 'up') { 96 | if (i === 0) return apps; 97 | const tmp = apps[i]; 98 | apps[i] = apps[i - 1]; 99 | apps[i - 1] = tmp; 100 | } else if (direction === 'down') { 101 | if (i === apps.length - 1) return apps; 102 | const tmp = apps[i]; 103 | apps[i] = apps[i + 1]; 104 | apps[i + 1] = tmp; 105 | } 106 | return apps; 107 | }); 108 | }; 109 | 110 | const delApp = (i: number) => { 111 | setApps((apps) => apps.filter((_, j) => i != j)); 112 | }; 113 | 114 | const exportResFile = async () => { 115 | if (!resFile || !resName) return; 116 | setLoading(true); 117 | const newResFile = resFile.clone(); 118 | const appsData = await Promise.all( 119 | apps.map((appName) => getFile(`/files/app/${appName}`)) 120 | ); 121 | appsData.forEach((d) => newResFile.assets.push(new ResAsset(d))); 122 | const newResBin = newResFile.pack(); 123 | const newResName = 124 | 'RES_' + 125 | (resName.endsWith('res') 126 | ? resName.replace('.res', `_${Date.now()}.res`) 127 | : `_${Date.now()}.res`); 128 | downloadArrayBuffer(newResBin, newResName); 129 | setLoading(false); 130 | }; 131 | 132 | return ( 133 | <> 134 | 135 |

Res Builder

136 |

137 | {resName 138 | ? 'Select apps to build a .res file' 139 | : 'Select your FW version'} 140 |

141 | 142 | 143 | {/* FW selector */} 144 | {loading ? ( 145 | 146 | ) : ( 147 | <> 148 | 149 | 165 | 166 | 167 | 168 | )} 169 | 170 | {resName && resFile && ( 171 | <> 172 | {/* App selector */} 173 | 174 |
175 |
176 | 177 |
178 | Selected apps: 179 |
180 | {apps.map((appName, i) => ( 181 | 188 | ))} 189 |
190 |
191 | 192 |
193 |
194 | 201 |
202 |
203 | 210 |
211 |
212 |
213 |
214 |
215 | 216 | 217 | {/* Show apps list */} 218 | 219 |
220 |
221 | App list: 222 | {Object.keys(files.app) 223 | .filter((a) => !apps.includes(a as any)) 224 | .map((appName: any) => ( 225 |
226 | 232 | 233 |
234 | ))} 235 |
236 |
237 | 238 | 239 | )} 240 | 241 | {resName === 'custom' && !resFile && ( 242 | <> 243 | 244 |
245 | You haven't yet created a custom .res file. 246 |
247 |
248 | 255 | 256 | 257 | )} 258 | 259 | ); 260 | } 261 | 262 | function SystemAssets({ 263 | res, 264 | onEdit, 265 | }: { 266 | res: ResFileWrapped; 267 | onEdit(): void; 268 | }) { 269 | const renderTooltip = (props: any) => ( 270 | Select "custom" res to edit system assets 271 | ); 272 | 273 | const renderEditBtn = () => ( 274 | 277 | ); 278 | 279 | return ( 280 |
281 | {res.name === 'custom' ? ( 282 | renderEditBtn() 283 | ) : ( 284 | 285 | {renderEditBtn()} 286 | 287 | )} 288 |  system 289 |  system assets ({byteToKB(res.file.size())}) 290 |
291 | ); 292 | } 293 | 294 | function SelectedApp({ 295 | moveApp, 296 | delApp, 297 | appName, 298 | i, 299 | }: { 300 | appName?: AppName; 301 | moveApp?(direction: 'up' | 'down', i: number): void; 302 | delApp?(i: number): void; 303 | i: number; 304 | }) { 305 | return ( 306 |
307 | 316 |   317 | 326 |   327 | 330 | {appName && } 331 |
332 | ); 333 | } 334 | 335 | function AppLabel({ appName }: { appName: AppName }) { 336 | const metaData = getELFMetadata(appName); 337 | const nameParts = appName.split('-'); 338 | const prefix = nameParts.shift(); 339 | const name = nameParts.join('-'); 340 | return ( 341 | <> 342 | {' '} 343 | {prefix} 344 | {' '} 345 | {metaData.forum ? ( 346 | 352 | {name} 353 | 354 | ) : ( 355 | <>{name} 356 | )} 357 | {' '} ({getELFSize(appName)}) 358 | 359 | ); 360 | } 361 | 362 | const byteToKB = (i: number) => `${Math.round(i / 1024)}KB`; 363 | 364 | export function ResSize({ 365 | res, 366 | apps, 367 | }: { 368 | res: ResFileWrapped; 369 | apps: AppName[]; 370 | }) { 371 | const THRESHOLD_WARN = 750 * 1024; 372 | const MAX_RES_SIZE = 800 * 1024; 373 | let sumSize = res.file.size(); 374 | for (const app of apps) { 375 | sumSize += files.app[app].size; 376 | } 377 | const precent = Math.min(100, (sumSize * 100) / MAX_RES_SIZE); 378 | 379 | return ( 380 | <> 381 | File size: 382 |
383 |
384 |
THRESHOLD_WARN ? 'bg-danger' : ''}`} 386 | role="progressbar" 387 | style={{ width: precent + '%', fontSize: '1.3em' }} 388 | > 389 | {byteToKB(sumSize)} / {byteToKB(MAX_RES_SIZE)} 390 |
391 |
392 | {sumSize > THRESHOLD_WARN && ( 393 |

394 | 395 | File is too big. You may not be able to upload it to the watch. 396 |
397 | Please consider removing some apps. 398 |
399 |

400 | )} 401 | 402 | ); 403 | } 404 | -------------------------------------------------------------------------------- /src/components/ResBuilder/ResEditor.tsx: -------------------------------------------------------------------------------- 1 | import { BipBitmap, ResAsset, ResFile } from 'amazfit-bip-tools-ts'; 2 | import { useEffect, useState } from 'react'; 3 | import { 4 | ResFileWrapped, 5 | getResByName, 6 | loadAllRes, 7 | saveCustomRes, 8 | } from './ResUtils'; 9 | import { Button, Card, Col, Spinner } from 'react-bootstrap'; 10 | import { byteToKB, delay, downloadArrayBuffer } from '../Utils'; 11 | 12 | export function ResEditor({ 13 | onChangeViewToApps, 14 | }: { 15 | onChangeViewToApps(): void; 16 | }) { 17 | const [listUsableRes, setListUsableRes] = useState([]); 18 | const [loading, setLoading] = useState(true); 19 | const [res, setResNoPostProcess] = useState(); 20 | 21 | const setRes = async (res?: ResFile) => { 22 | setLoading(true); 23 | if (res) { 24 | for (const asset of res.assets) { 25 | if (asset.type() !== 'bm') continue; 26 | decodeBMAsset(asset); 27 | await delay(0); 28 | } 29 | } 30 | setResNoPostProcess(res); 31 | setLoading(false); 32 | }; 33 | 34 | // get current res file 35 | useEffect(() => { 36 | (async () => { 37 | setListUsableRes((await loadAllRes()).filter((r) => r.name !== 'custom')); 38 | setRes((await getResByName('custom'))?.file); 39 | })(); 40 | }, []); 41 | 42 | const renderLoading = () => ( 43 | 44 |
45 |
46 | 47 |
48 | Please wait... 49 | 50 | ); 51 | 52 | const renderPicker = () => ( 53 | 54 | Pick a base .res file: 55 |
56 |
57 | {listUsableRes.map((r) => ( 58 |
59 | 67 |
68 | ))} 69 | 70 | ); 71 | 72 | const renderAssetEditor = () => { 73 | if (!res) return null; 74 | return ( 75 | <> 76 | 77 |
78 |
79 | Number of assets: {res.assets.length.toString().padStart(4, '0')} 80 |     81 | 97 |
98 |
99 | 100 | {res.assets.map((asset, i) => { 101 | return ; 102 | })} 103 |
104 |
105 |
106 |
107 |
108 |
109 | 110 | ); 111 | }; 112 | 113 | return ( 114 | <> 115 | 116 |

117 | {' '} 120 | Res Editor 121 |

122 | 123 | 124 | {loading ? renderLoading() : res ? renderAssetEditor() : renderPicker()} 125 | 126 | ); 127 | } 128 | 129 | interface BMType { 130 | hash: string; 131 | asset: ResAsset; 132 | bm: BipBitmap; 133 | url: string; 134 | } 135 | const BM_CACHE: { [hash: string]: BMType } = {}; 136 | const decodeBMAsset = (asset: ResAsset) => { 137 | const hash = asset.hash(); 138 | if (BM_CACHE[hash]) { 139 | return BM_CACHE[hash]; 140 | } 141 | const bm = new BipBitmap(asset); 142 | const blob = new Blob([bm.toBMP()], { type: 'image/bmp' }); 143 | const url = URL.createObjectURL(blob).toString(); 144 | const entry = { asset, bm, url, hash }; 145 | BM_CACHE[hash] = entry; 146 | return entry; 147 | }; 148 | 149 | function DisplayAsset({ asset, i }: { asset: ResAsset; i: number }) { 150 | const type = asset.type(); 151 | const idx = i.toString().padStart(4, '0'); 152 | 153 | const renderPreview = () => { 154 | if (type === 'bm') { 155 | const bm = decodeBMAsset(asset); 156 | return ( 157 |
158 | 159 |
160 | ); 161 | } else { 162 | return ( 163 |
164 | Asset type: {type} 165 |
166 | Size: {byteToKB(asset.data.byteLength)} 167 |
168 |
169 | (This asset is not a bitmap) 170 |
171 |
172 | ); 173 | } 174 | }; 175 | 176 | return ( 177 | 178 | 179 | Index: {idx} 180 | {renderPreview()} 181 |
182 | 197 |   198 | 204 |
205 |
206 | 207 | ); 208 | } 209 | -------------------------------------------------------------------------------- /src/components/ResBuilder/ResUtils.ts: -------------------------------------------------------------------------------- 1 | import files from '../../data/files.json'; 2 | import { ResAsset, ResFile } from 'amazfit-bip-tools-ts'; 3 | import { ResName } from '../Utils'; 4 | 5 | export type ResWrappedName = ResName | 'custom'; 6 | 7 | export class ResFileWrapped { 8 | name: ResWrappedName; 9 | file: ResFile; 10 | constructor(name: ResWrappedName, file: ResFile) { 11 | this.name = name; 12 | this.file = file; 13 | } 14 | clone() { 15 | const buf = this.file.pack(); 16 | return new ResFile(buf); 17 | } 18 | } 19 | 20 | const RES_CACHE: ResFileWrapped[] = []; 21 | 22 | export async function loadAllRes() { 23 | if (RES_CACHE.length > 0) { 24 | return RES_CACHE; 25 | } 26 | 27 | const remoteFiles = await Promise.all( 28 | Object.keys(files.res).map(async (resName) => { 29 | const resFile = await ResFile.fromURL(`/files/res/${resName}`); 30 | const libbipFile = await fetch( 31 | `/files/libbip/${resName.replace('.res', '.bin')}` 32 | ); 33 | const libbipBuf = new Uint8Array(await libbipFile.arrayBuffer()); 34 | resFile.assets.push(new ResAsset(libbipBuf)); 35 | const wrapped = new ResFileWrapped(resName as any, resFile); 36 | return wrapped; 37 | }) 38 | ); 39 | 40 | for (const f of remoteFiles) { 41 | RES_CACHE.push(f); 42 | } 43 | 44 | const savedResBuf = await loadSavedBuffer(); 45 | if (savedResBuf) { 46 | const resFile = new ResFile(savedResBuf); 47 | RES_CACHE.push(new ResFileWrapped('custom', resFile)); 48 | } 49 | 50 | return RES_CACHE; 51 | } 52 | 53 | export async function getResByName(name: ResWrappedName) { 54 | const list = await loadAllRes(); 55 | return list.find((e) => e.name === name); 56 | } 57 | 58 | export async function saveCustomRes(res?: ResFile) { 59 | const idx = RES_CACHE.findIndex((r) => r.name === 'custom'); 60 | if (res) { 61 | if (idx > -1) { 62 | RES_CACHE[idx] = new ResFileWrapped('custom', res); 63 | } else { 64 | RES_CACHE.push(new ResFileWrapped('custom', res)); 65 | } 66 | await saveBuffer(res.pack()); 67 | } else { 68 | if (idx > -1) RES_CACHE.splice(idx, 1); 69 | localStorage.removeItem(STORAGE_KEY_CUSTOM_RES); 70 | } 71 | } 72 | 73 | ///////////////////// 74 | 75 | const STORAGE_KEY_CUSTOM_RES = 'ngxson_custom_res'; 76 | 77 | async function saveBuffer(buf: Uint8Array) { 78 | const blob = new Blob([buf], { type: 'application/octet-binary' }); 79 | const reader = new FileReader(); 80 | reader.readAsDataURL(blob); 81 | reader.onloadend = () => { 82 | if (reader.result) { 83 | localStorage.setItem(STORAGE_KEY_CUSTOM_RES, reader.result as string); 84 | } 85 | }; 86 | } 87 | 88 | async function loadSavedBuffer(): Promise { 89 | const savedBlobStr = localStorage.getItem(STORAGE_KEY_CUSTOM_RES); 90 | if (!savedBlobStr) { 91 | return null; 92 | } 93 | 94 | const res = await fetch(savedBlobStr); 95 | const buf = new Uint8Array(await res.arrayBuffer()); 96 | return buf; 97 | } 98 | -------------------------------------------------------------------------------- /src/components/ResBuilder/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import AppPicker from './AppPicker'; 3 | import { ResEditor } from './ResEditor'; 4 | 5 | export default function ResBuilder() { 6 | const [view, setView] = useState<'apps' | 'edit'>('apps'); 7 | return view === 'apps' ? ( 8 | setView('edit')} /> 9 | ) : ( 10 | setView('apps')} /> 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/components/Utils.ts: -------------------------------------------------------------------------------- 1 | import { saveAs } from 'file-saver'; 2 | import files from '../data/files.json'; 3 | 4 | export type ResDataType = keyof typeof files; 5 | export type FWName = keyof typeof files.fw; 6 | export type ResName = keyof typeof files.res; 7 | export type AppName = keyof typeof files.app; 8 | export type FontName = keyof typeof files.font; 9 | export type LibbipName = keyof typeof files.libbip; 10 | 11 | export interface ResBinaryPayload { 12 | header: Uint8Array; 13 | resTable: Uint8Array[]; 14 | } 15 | 16 | export interface ResPayload { 17 | res: ResName; 18 | apps: AppName[]; 19 | } 20 | 21 | export const byteToKB = (i: number) => `${Math.round(i / 1024)}KB`; 22 | 23 | export function getELFMetadata(filename: AppName) { 24 | return files.app[filename] || {}; 25 | } 26 | 27 | export function getELFSize(filename: AppName) { 28 | return byteToKB(files.app[filename].size); 29 | } 30 | 31 | export function getResBaseSize(filename: ResName) { 32 | return byteToKB(files.res[filename].size); 33 | } 34 | 35 | export function getLibBipSize(filename: LibbipName) { 36 | return byteToKB(files.libbip[filename].size); 37 | } 38 | 39 | export async function downloadArrayBuffer(buf: Uint8Array, filename: string) { 40 | saveAs(new Blob([buf], { type: 'application/octet-stream' }), filename); 41 | } 42 | 43 | export const delay = (ms: number) => new Promise((r) => setTimeout(r, ms)); 44 | -------------------------------------------------------------------------------- /src/data/files.json: -------------------------------------------------------------------------------- 1 | { 2 | "fw": { 3 | "BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.fw": { 4 | "size": 490164 5 | }, 6 | "BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.fw": { 7 | "size": 490164 8 | }, 9 | "BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.fw": { 10 | "size": 476820 11 | } 12 | }, 13 | "res": { 14 | "BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.res": { 15 | "size": 367462 16 | }, 17 | "BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.res": { 18 | "size": 367462 19 | }, 20 | "BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.res": { 21 | "size": 473680 22 | } 23 | }, 24 | "app": { 25 | "game-2048-v0.3-by-zener79.elf": { 26 | "forum": "https://github.com/giovantenne/2048-bipos", 27 | "desc": "2048 Game", 28 | "size": 11092 29 | }, 30 | "game-4letters-by-x27.elf": { 31 | "forum": "", 32 | "desc": "4 Letters Game", 33 | "size": 37732 34 | }, 35 | "game-Breakout-by-PRO100KBAC.elf": { 36 | "forum": "", 37 | "desc": "Breakout Game", 38 | "size": 29000 39 | }, 40 | "game-Magic8BallRU-by-erekoze.elf": { 41 | "forum": "", 42 | "desc": "Magic 8 Balls Game (Russian)", 43 | "size": 26652 44 | }, 45 | "game-Minesweeper-by-x27.elf": { 46 | "forum": "", 47 | "desc": "Minesweeper Game", 48 | "size": 8388 49 | }, 50 | "game-PingPong-by-PRO100KBAC.elf": { 51 | "forum": "", 52 | "desc": "Ping Pong Game", 53 | "size": 28180 54 | }, 55 | "game-Snake-by-PRO100KBAC.elf": { 56 | "forum": "", 57 | "desc": "Snake Game", 58 | "size": 37472 59 | }, 60 | "game-SokobanBIP-v1.1-by-000edu.elf": { 61 | "forum": "", 62 | "desc": "Sokoban Game", 63 | "size": 87220 64 | }, 65 | "game-TRex-by-Yuukari.elf": { 66 | "forum": "https://github.com/yuukari/TRex", 67 | "desc": "T-Rex Game (a.k.a Chrome T-Rex)", 68 | "size": 28388 69 | }, 70 | "game-TetrisBIP-v1.3-by-000edu.elf": { 71 | "forum": "", 72 | "desc": "Tetris Game", 73 | "size": 17616 74 | }, 75 | "game-boxpop-v1.1-by-x27.elf": { 76 | "forum": "", 77 | "desc": "Box Pop Game", 78 | "size": 12620 79 | }, 80 | "game-fifteen-by-x27.elf": { 81 | "forum": "", 82 | "desc": "Fifteen Game", 83 | "size": 7512 84 | }, 85 | "game-flappybird-v0.2.7-by-PRO100KBAC.elf": { 86 | "forum": "", 87 | "desc": "Flappy Bird Game", 88 | "size": 31060 89 | }, 90 | "game-unblockme-by-x27.elf": { 91 | "forum": "", 92 | "desc": "Unblock Me Game", 93 | "size": 39612 94 | }, 95 | "hook-alarm-manager-by-MNVolkov.elf": { 96 | "forum": "https://github.com/ngxson/hobby-amazfit-bip-web/blob/master/archive/myamazfit-0.en.md", 97 | "desc": "Alarm Manager", 98 | "size": 9616 99 | }, 100 | "hook-animated-menu.elf": { 101 | "forum": "", 102 | "desc": "Animated Menu Items", 103 | "size": 177316 104 | }, 105 | "hook-simpleDND-by-MNVolkov.elf": { 106 | "forum": "https://github.com/MNVolkov/simpleDND", 107 | "desc": "Add features to DND (swipe-down) screen", 108 | "size": 16664 109 | }, 110 | "utility-BTNotes-v3.0-by-ngxson.elf": { 111 | "forum": "https://github.com/ngxson/hobby_amazfit_bip_bt_notes", 112 | "desc": "This app allows you to save notification as note. Notes can be preserved even after you clear all notifications. ", 113 | "size": 16564 114 | }, 115 | "utility-BipCounter-v2.4-by-erekoze.elf": { 116 | "forum": "", 117 | "desc": "Simple counter app (tap to count up)", 118 | "size": 14260 119 | }, 120 | "utility-GoHome-by-MikhailU.elf": { 121 | "forum": "", 122 | "desc": "Go Home - simplified GPS Returner analog using the compass", 123 | "size": 28420 124 | }, 125 | "utility-NotesBIPAqua-v1.1-by-000edu.elf": { 126 | "forum": "", 127 | "desc": "Simple note editor app (Aqua color theme)", 128 | "size": 46932 129 | }, 130 | "utility-NotesBIPPurple-v1.1-by-000edu.elf": { 131 | "forum": "", 132 | "desc": "Simple note editor app (Purple color theme)", 133 | "size": 46928 134 | }, 135 | "utility-SafeBoxBIP-v1.1-by-000edu.elf": { 136 | "forum": "", 137 | "desc": "Simple app for storing passwords, PIN codes", 138 | "size": 47060 139 | }, 140 | "utility-calculator-by-MNVolkov.elf": { 141 | "forum": "https://github.com/ngxson/hobby-amazfit-bip-web/blob/master/archive/myamazfit-0.en.md", 142 | "desc": "The Calculator app allows you to perform basic arithmetic operations", 143 | "size": 10156 144 | }, 145 | "utility-calendar-by-MNVolkov.elf": { 146 | "forum": "https://github.com/ngxson/hobby-amazfit-bip-web/blob/master/archive/myamazfit-0.en.md", 147 | "desc": "The Calendar app displays the calendar for the current month and any selected month of any year.", 148 | "size": 10036 149 | }, 150 | "utility-flashlight-by-MNVolkov.elf": { 151 | "forum": "https://github.com/ngxson/hobby-amazfit-bip-web/blob/master/archive/myamazfit-0.en.md", 152 | "desc": "The simple Flashlight app is designed to illuminate things using the screen's backlight LEDs", 153 | "size": 5884 154 | }, 155 | "utility-gps-returner-by-x27.elf": { 156 | "forum": "", 157 | "desc": "Return to a defined point via GPS", 158 | "size": 28712 159 | }, 160 | "utility-metronome-by-ngxson.elf": { 161 | "forum": "https://github.com/ngxson/hobby_amazfit_bip_metronome", 162 | "desc": "Simple Metronome app, useful for meditation or for playing musical instruments", 163 | "size": 6808 164 | }, 165 | "utility-music-control-by-MNVolkov.elf": { 166 | "forum": "https://github.com/MNVolkov/Music_Control", 167 | "desc": "Remote control your favorite music player on your phone. Phone host app can be used are: Amazfit MOD, GadgetBridge or LikeApp", 168 | "size": 34388 169 | }, 170 | "utility-navigator-Marlen-Maksumov.elf": { 171 | "forum": "", 172 | "desc": "(no description)", 173 | "size": 29812 174 | }, 175 | "utility-vietnamese-calendar-by-ngxson.elf": { 176 | "forum": "https://github.com/ngxson/hobby_amazfit_bip_am_lich", 177 | "desc": "Vietnamese Calendar (Lunar Calendar)", 178 | "size": 10004 179 | }, 180 | "watchface-abstract-by-ssp1971.elf": { 181 | "forum": "", 182 | "desc": "(no description)", 183 | "size": 58776 184 | }, 185 | "watchface-keanu-by-MNVolkov.elf": { 186 | "forum": "", 187 | "desc": "(no description)", 188 | "size": 175176 189 | }, 190 | "watchface-mickey-by-usb.elf": { 191 | "forum": "", 192 | "desc": "(no description)", 193 | "size": 175148 194 | } 195 | }, 196 | "font": { 197 | "BOLD_V6.2_not_latin.ft": { 198 | "size": 174922 199 | }, 200 | "BOLD_v4q_newsmiles.ft": { 201 | "size": 74335 202 | }, 203 | "Vietnamese_Emoji_v5.3.ft": { 204 | "size": 97090 205 | } 206 | }, 207 | "libbip": { 208 | "BipOS_0.5.5_b5_not_latin_1.1.2.05_ENGLISH.bin": { 209 | "size": 752 210 | }, 211 | "BipOS_0.5.5_b7_not_latin_1.1.2.05_ENGLISH.bin": { 212 | "size": 800 213 | }, 214 | "BipOS_0.5.5_b7_not_latin_1.1.5.36_MULTILANG.bin": { 215 | "size": 744 216 | } 217 | } 218 | } -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | 15 | .nui-app-item { 16 | box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.2); 17 | transition: 0.3s; 18 | border-radius: 5px; 19 | padding: 0.2em; 20 | margin: 0.2em; 21 | } 22 | 23 | a.forum::after { 24 | content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAQElEQVR42qXKwQkAIAxDUUdxtO6/RBQkQZvSi8I/pL4BoGw/XPkh4XigPmsUgh0626AjRsgxHTkUThsG2T/sIlzdTsp52kSS1wAAAABJRU5ErkJggg==); 25 | margin: 0 3px 0 5px; 26 | } 27 | 28 | .app-label { 29 | display: inline-block; 30 | padding: 0.1em 0.5em; 31 | border-radius: 100px; 32 | color: white; 33 | } 34 | 35 | .app-label.system { 36 | background-color: #909090; 37 | } 38 | .app-label.game { 39 | background-color: #e83e8c; 40 | } 41 | .app-label.utility { 42 | background-color: #6cc3d5; 43 | } 44 | .app-label.hook { 45 | background-color: #6f42c1; 46 | } 47 | .app-label.watchface { 48 | background-color: #cca550; 49 | } 50 | 51 | .asset { 52 | padding: 0.5em; 53 | width: 100%; 54 | margin-bottom: 1em; 55 | } 56 | .asset .img-view { 57 | margin-bottom: 0.7em; 58 | overflow: hidden; 59 | height: 176px; 60 | width: 176px; 61 | border: 1px solid #aaa; 62 | background-color: #ddd; 63 | } 64 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | //import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import App from './App.tsx'; 4 | import './bootstrap.min.css'; 5 | import './index.css'; 6 | 7 | ReactDOM.createRoot(document.getElementById('root')!).render( 8 | // disable strict mode because it breaks loadAllRes() on dev 9 | // 10 | 11 | // 12 | ); 13 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "useDefineForClassFields": true, 5 | "lib": ["ES2020", "DOM", "DOM.Iterable"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "resolveJsonModule": true, 13 | "isolatedModules": true, 14 | "noEmit": true, 15 | "jsx": "react-jsx", 16 | 17 | /* Linting */ 18 | "strict": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "noFallthroughCasesInSwitch": true 22 | }, 23 | "include": ["src"], 24 | "references": [{ "path": "./tsconfig.node.json" }] 25 | } 26 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "skipLibCheck": true, 5 | "module": "ESNext", 6 | "moduleResolution": "bundler", 7 | "allowSyntheticDefaultImports": true, 8 | "strict": true 9 | }, 10 | "include": ["vite.config.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | }); 8 | --------------------------------------------------------------------------------