TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
Настольное приложение для учёта задач, времени и заработка (Electron, Windows): проекты, таймер, календарь, экспорт в Excel, тёмная/светлая тема, интерфейс на 4 языках
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Настольное приложение (Electron) для ведения задач, учёта времени и заработка. Раньше называлось «Task Timer». Папка проекта осталась task-timer/, но приложение, exe и данные теперь Lancible. Данные из %APPDATA%\task-timer\ переносятся автоматически при первом запуске. Установщики для Windows и macOS собираются на GitHub Actions (.github/workflows/release.yml — macOS-раннер обязателен, electron-builder отказывается собирать .dmg не на самом маке) и публикуются на странице релизов:README 전문 보기 ↗
Настольное приложение (Electron) для ведения задач, учёта времени и заработка.
Раньше называлось «Task Timer». Папка проекта осталась
task-timer/, но приложение, exe и данные теперьLancible. Данные из%APPDATA%\task-timer\переносятся автоматически при первом запуске.
Установщики для Windows и macOS собираются на GitHub Actions
(.github/workflows/release.yml — macOS-раннер обязателен, electron-builder
отказывается собирать .dmg не на самом маке) и публикуются на странице
релизов:
Lancible Setup *.exeLancible-*.dmg (universal — подходит и Apple Silicon, и Intel)Все релизы: https://github.com/lancibleofficial/Lancible/releases
Ни один из установщиков пока не подписан платным сертификатом (Windows Authenticode / Apple Developer ID) — ОС может предупредить о неизвестном разработчике. На Windows — «Подробнее» → «Выполнить в любом случае»; на маке — правый клик по приложению → «Открыть».
prefers-color-scheme ОС).
Переключатель — три icon-таба (монитор/солнце/луна) внизу левого рейла
(.theme-tabs, клик сразу выбирает тему, а не циклит), сохраняется в
settings.theme. Палитра — CSS-переменные (--bg, --panel, --accent, …)
в src/renderer/styles.css; тёмная (по умолчанию): #2A2B2E фон ·
#5A5A66 границы · #69D345 основной акцент · #7ADD58 hover
акцентных кнопок. Светлая палитра: #F6F7F3 фон · #EEF1EA вторичные
панели, чисто белые (--panel: #ffffff) карточки там, где раньше был
приглушённо-серый --panel-2 (например «Недавние задачи», .rtile), чтобы
не выглядеть грязно. Акцент на светлой теме — тот же оттенок, что
и на тёмной, но гуще (#63C841, hover #56B337); зелёный текст и значки
на светлом — отдельный токен --accent-ink (#1F7A12, не ниже 4.5:1 на любой
подложке). --accent-text в обеих темах тёмный #0D1A07, а не белый:
подпись на зелёной кнопке иначе была бы нечитаемой. Ссылки в
редакторе — отдельный токен --link (голубой, #5EC8F2 тёмная / #1C72B0
светлая), не завязан на акцент.titleBarOverlay) красятся тем, что лежит под ними. Цветов
в src/main.js нет: окно (syncTitlebarOverlay() в app.js) читает фон
поверхности под кнопками — шапки, а в полноэкранном редакторе его панели — и
токен --text-dim и шлёт их как window.api.setTitlebarOverlay(theme, {color, symbolColor}) → IPC theme:set-overlay; main проверяет #rrggbb и
передаёт в setTitleBarOverlay. Зовётся при старте, смене темы, входе в
полноэкранный редактор и выходе из него (onFullscreen редактора) и когда ОС
переключилась между светлой/тёмной в режиме «Системная» (matchMedia).
Окно создаётся скрытым и показывается, когда нарисована первая страница и
пришли цвета, — иначе оно мигнуло бы чужой подложкой. Полноэкранный редактор
оставляет место под кнопки: справа на Windows/Linux (env(titlebar-area-*)),
слева на маке (--traffic-w). Проверяет npm run smoke.[data-ovs]), а своя — тонкий бегунок на дорожке .ovs-track у
правого края — рисуется, пока область крутят или над ней мышь, и
гаснет через секунду; бегунок тянется, щелчок по дорожке листает. Цвет —
токены --scrollbar и --scrollbar-hover. Подключает
attachOverlayScroll в app.js по списку OVS_AREAS. Вбок полосы нет
совсем: ряд карточек «Проектов», дорожки доски и переключатель режимов
«Времени» на узкой ширине листаются без неё — край, за которым есть что
листать, растворяется, а у края стоит кнопка-стрелка на подложке
(attachScrollEdges, список EDGE_AREAS, компонент «Край ленты» в
DESIGN.md). Там, куда он не
дотянулся (текст редактора), остаётся нативная тонкая полоса — только
::-webkit-scrollbar*, без scrollbar-width/scrollbar-color: в
Chromium если на элементе заданы обе группы свойств одновременно, побеждают
стандартные и весь webkit-кастом молча игнорируется..woff2 и лицензия OFL лежат в assets/fonts/;
scripts/copy-vendor.js на postinstall делает из них точное зеркало в
src/renderer/vendor/fonts/. У каждого шрифта лицензия рядом — это сторожит
tests/unit/fonts-license.test.js.Menu.setApplicationMenu(null)); вместо него своя строка заголовка
#titlebar с логотипом-акцентом и кнопками окна через titleBarOverlay.
В dev-режиме F12 — DevTools, Ctrl+R — перезагрузка.src/renderer/styles.css.#69d345 на
графитовом скруглённом квадрате; исходник один — assets/logo-mark.svg
(монохромный, fill="currentColor"). node scripts/make-logo.js вписывает
его inline в .tb-logo-mark шапки, в шапку, подвал и героя лендинга и в
favicon каждой страницы; цвет в разметке не пишется — его задаёт токен акцента
(color: var(--accent-ink) у .tb-logo-mark, var(--accent) на лендинге).<select> —
с галочкой у текущего языка, через переиспользуемое плавающее меню
openMenu()/#ctx-menu; сохраняется в settings.lang). Перевод — таблица T в
начале src/renderer/app.js + t('ключ', {подстановки}); статичная разметка
размечена атрибутами data-i18n/data-i18n-ph/data-i18n-title/data-i18n-aria
и применяется через applyStaticTranslations(). Множественное число — по
языковым правилам (pluralForm, слав. 1/2-4/5+ для ru/uk, en — sing/plur,
kk — без словоизменения). Даты/числа — через Intl/toLocaleDateString с
локалью текущего языка (LOCALE_MAP). Собственные данные пользователя
(названия проектов/задач, тексты заметок) не переводятся — язык влияет только
на интерфейс.#titlebar, как в Kaspersky Premium): логотип + название слева
(размер логотипа не меняется — только позиция), рядом широкая строка поиска;
результаты выпадают прямо под ней. Правее — системные кнопки окна
(titleBarOverlay).#navrail): разделы Обзор / Календарь, кнопка Свернуть
(рейл плавно сжимается до иконок вместе с логотипом в шапке — анимация через
transition: width/margin-left на элементах, вынесенных из flex-потока в
position: absolute; состояние — в ui.navCollapsed).Ctrl+F): по проектам и задачам,
результаты отдельными группами (название на отдельной строке над подписью —
проектом/статусом); у задачи показано, к какому проекту она относится;
↑↓/Enter для выбора; клик вне панели или Esc закрывают её.core/route.js): экран и открытая сущность лежат в хэше —
#/today, #/projects, #/project/<id>[/board|versions|docs], #/task/<id>,
#/docs, #/doc/<id>, #/stats[/day|week|month|agenda], #/settings.
Адрес пишет сам render() (syncRoute()): новый экран — запись в истории,
вкладка проекта и режим «Статистики» — замена записи; «назад/вперёд» ходят по
экранам. Обновление страницы остаётся на месте; кривая ссылка и сущность, которой
нет, — «Сегодня» с заменой адреса (старый #/time разбирается как #/stats).
Если вошли в аккаунт, а проекта по ссылке ещё нет, запуск ждёт первую
синхронизацию (не дольше 8 секунд). На десктопе последний экран запоминается
(ui.route), а lancible://project/<id>, lancible://task/<id> и
lancible://doc/<id> открывают приложение сразу на нём (route:open). «Скопировать
ссылку» в меню проекта и задачи кладёт веб-ссылку (…/app/#/project/<id>).#topbar) — только на «Обзоре»: 4 крупные
карточки (всего проработано, всего заработано, заработано в этом месяце —
от начала до конца текущего месяца, задач выполнено) + чип работающего таймера.--icon), не эмодзи.#home-view)#home-view сам — сетка на 2 колонки (grid-template-columns: 1fr 300px)
во всю высоту вида: слева .home-center (скроллящийся контент + прибитые
снизу «Недавние задачи»), справа #home-side — календарная панель тянется
от самого верха до самого низа окна, а не только на высоту левой сетки.
Статистика (#topbar) лежит внутри .home-main, поэтому её правый край
упирается ровно в границу календарной панели; линия-разделитель под
статистикой убрана (только отступ). Заголовок секции «Проекты · N» и кнопка
«Создать проект» (.home-head) — flex-wrap, кнопка переносится под
заголовок на узком окне вместо наползания на текст.+
полного размера. Закреплённые — в одну строку с горизонтальной
прокруткой (.car-track, padding подобран так, чтобы hover-тень плитки не
обрезалась краем скролл-контейнера). Остальные — плитки идут слева
направо и переносятся на новую строку (.projects-grid, обычный
flex-wrap; сами плитки в этой сетке могут сжиматься flex:0 1 250px —
иначе на узком окне фикс-ширина 250px тянула за собой нежеланный
горизонтальный скролл всей главной), без горизонтального скролла; при
нехватке места вся левая колонка скроллится вертикально. Стрелки карусели
(в обеих группах) не дизейблятся с тусклой иконкой, а полностью
скрываются, когда скроллить в эту сторону некуда, и появляются по мере
прокрутки.#recent-section.recent-fixed, вне зоны прокрутки .home-grid, с той же
заливкой фона и линией-разделителем сверху); ряд маленьких плиток (белый
фон --panel, а не приглушённый --panel-2, чтобы не выглядеть тускло —
чекбокс, название, проект, время), прокручивается горизонтально.
Выполненные задачи в этот список не попадают.#calendar-view).cal-nav, чтобы на узком окне она
переносилась как единый блок, а не рассыпалась по одной кнопке на строку;
правая панель календаря — minmax(220px, 340px) (не жёсткие 340px), чтобы
левой колонке оставалось больше места на минимальной ширине окна. В Дне —
почасовая раскладка на 24 строки: часы без записей приглушены, часы с
сессиями показывают чипы задач (цвет — проекта); клик по чипу открывает
задачу. Строка часа не сжимается флексом ниже своего реального содержимого
(flex-shrink: 0 — раньше при большом количестве чипов в одном часе флекс
ужимал .hour-row до min-height и чипы визуально вылезали за её границы);
сами чипы при этом остаются сжимаемыми и переносят длинный текст по словам,
а не растягивают всю раскладку по горизонтали.--panel-2/--border, без акцентного тона —
раньше был зеленоватый color-mix с акцентом) — независимо от того, включён
ли ниже режим периода.openDatePicker(anchor, value, onPick) под оба места.session.rate) — смена ставки не
переписывает историю.core/duplicate.js.confirm()),
стилизованный под приложение, — и правее всех, у самого края, переключатель
вкладок «Заметки» / «История». Строка заголовка — flex-wrap, а поле
названия держит min-width: 140px: на узком окне вкладки переносятся на
свою строку, но название задачи никогда не сжимается до нечитаемой ширины
(было — пропадало полностью на минимальной ширине окна).
--link, голубые — отдельный от акцента токен). Подсказка ссылки
(URL + Edit/Remove) теперь не обрезается — контейнер редактора держит
скруглённые углы на тулбаре/поле ввода напрямую, а не через overflow:hidden
на обёртке (которая раньше срезала всплывающую подсказку) — и не вылезает за
границы редактора: Quill сконфигурирован с bounds: '#editor-wrap', так что
сам позиционирует/переносит подсказку внутри карточки редактора, а не всей
страницы. «Remove» в подсказке — красный (--danger), не синий.
Таблицы (кнопка ▦): когда курсор в таблице — панель под редактором:
строки/столбцы + заливка ячейки / строки / столбца цветом (через блочный
атрибутор , попадает в Delta).время × ставка = заработано вживую.SUM. Формат
генерируется без сторонних библиотек (src/xlsx.js).scale(.97)),
модалки (popIn), тосты. Уважает prefers-reduced-motion.₽→RUB), проектам добавляются color/description/pinnedAt,
задачам — pinnedAt, сессиям — rate (у старых берётся текущая ставка),
в ui — navCollapsed.npm install
npm start
npm install заодно копирует файлы редактора Quill в src/renderer/vendor/
(скрипт scripts/copy-vendor.js).
npm run build:exe # Windows — можно собирать на любой ОС
npm run build:dmg # macOS — только на самом маке (ограничение electron-builder)
build:exe — это:
npm run icon — рисует build/icon.ico и build/icon.png (1024×1024,
графит + акцентный знак из assets/logo-mark.svg; icon.png —
заодно источник для .icns на маке, electron-builder конвертирует сам);npm run package:win — electron-builder собирает NSIS-инсталлятор
dist/Lancible Setup X.Y.Z.exe (one-click, ставится в
%LOCALAPPDATA%\Programs\Lancible, сам создаёт ярлыки на рабочем столе и в
«Пуск») + dist/latest.yml — метаданные для автообновления.build:dmg аналогично собирает dist/Lancible-X.Y.Z.dmg +
dist/Lancible-X.Y.Z-mac.zip (universal, arm64+x64) + dist/latest-mac.yml
через npm run package:mac.
Приложение обновляет себя само на обеих платформах: при запуске и затем
раз в час, пока оно открыто (только в собранном приложении, не в
npm start), src/main.js через
electron-updater тихо проверяет манифест (latest.yml/latest-mac.yml),
опубликованный в Supabase Storage (см. ниже); если версия новее — в левом
рейле снизу появляется зелёная кнопка «Доступно обновление»; клик скачивает
файл, кнопка становится «Перезапустить» — второй клик тихо ставит новую
версию и перезапускает приложение. Никакого мастера/диалогов между двумя
кликами не показывается (oneClick: true обязателен для этого на Windows —
без него quitAndInstall() открывает полный мастер установки и не завершает
процесс).
Состояние обновления (idle / downloading / ready) держит main и отдаёт
окну по update:status, поэтому кнопка переживает перезагрузку окна. В
подвале Настроек — «Lancible · <версия>» (на десктопе версию отдаёт
app:version, на вебе она записывается в web/version.js из корневого
package.json при сборке) и ссылка «Проверить обновления» — ручная проверка.
Публикация новой версии для автообновления (существующим пользователям):
"version" в package.json.npm run build:exe и/или npm run build:dmg.npm run publish:release — заливает всё, что нашлось в dist/
(.exe/.dmg/.zip + .blockmap + latest*.yml), в публичный Supabase
Storage bucket releases (нужны SUPABASE_URL/SUPABASE_SERVICE_ROLE_KEY
в .env, см. комментарий в scripts/publish-release.js — файл .env
никогда не коммитится). Так вручную — для своего хостинга: Supabase не
принимает файлы больше 50 МБ, а наши установщики весят 82 и 180 МБ. По тегу
всё делает CI, см. следующий абзац.Раздача установщиков из Cloudflare R2. Фид автообновления в Supabase
хранит только манифесты (latest.yml, latest-mac.yml), а сами файлы
раздаёт Cloudflare R2: GitHub Releases при замере 10 октября 2026 отдавал
~19 КБ/с (обновление в 82 МБ — больше часа), Cloudflare — ~18 МБ/с. GitHub
Releases остаются архивом и страницей «Скачать».
.github/workflows/release.yml по тегу v*: собирает установщики, публикует
GitHub Release, раскладывает файлы под именами из ссылок
(node scripts/publish-release.js artifacts --stage r2-stage), заливает их в
R2 по пути v<версия>/<имя файла> (aws s3 cp --endpoint-url https://<R2_ACCOUNT_ID>.r2.cloudflarestorage.com) и только после этого кладёт
в Supabase манифесты со ссылками <R2_PUBLIC_URL>/v<версия>/<имя файла>
(--release-base … --check-urls: каждая ссылка проверяется запросом HEAD).R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY (ключ API R2 с
правом записи в бакет), R2_BUCKET (имя бакета), R2_PUBLIC_URL (публичный
адрес бакета вида https://pub-….r2.dev — включить в настройках бакета,
«Public access» → «R2.dev subdomain»; без / на конце). Нужен и прежний
SUPABASE_SERVICE_ROLE_KEY. Пока R2-секреты заданы не все, выкат идёт
по-старому: ссылки в фиде ведут на GitHub, в логе — предупреждение.gh workflow run mirror-release.yml -f tag=v0.4.2 (Actions → Mirror release to
R2 → Run workflow). Он скачивает ассеты релиза, заливает их в R2 и
переопубликовывает манифесты; фид не откатывается — релиз старше версии в
latest.yml только добавляет файлы в R2.r2.dev у Cloudflare ограничен по частоте запросов и не
предназначен для постоянной раздачи; при появлении своего домена его
подключают к бакету (Settings → Custom Domains) и подставляют в
R2_PUBLIC_URL, а вышедшие версии переводит тот же mirror-release.yml..exe, .dmg, .apk) ведут в R2 на
конкретную версию (<R2_PUBLIC_URL>/<тег>/<файл>) и меняются вместе с
выпуском; их адрес и подпись над кнопкой сверяет tests/unit/landing.test.js.Раздача APK телефона из R2. APK (~96 МБ) раздаётся оттуда же, откуда
установщики десктопа: с GitHub Releases он шёл бы с той же скоростью
(~19 КБ/с). Лежит в том же бакете по пути mobile-v<версия>/Lancible-<версия>.apk
(например, <R2_PUBLIC_URL>/mobile-v1.2.2/Lancible-1.2.2.apk); GitHub Release
остаётся архивом. Секреты — те же пять R2_*.
.github/workflows/mobile-release.yml по тегу mobile-v*: собирает APK в EAS,
публикует GitHub Release, а при заданных секретах R2 заливает файл в бакет,
проверяет его запросом HEAD (ответ 200 и тот же размер, что у собранного) и
печатает готовый блок "android" для latest.json — в логе и на странице
выполнения задачи (node scripts/publish-release.js --mobile-apk <файл> --tag <тег> --public-url <R2_PUBLIC_URL>). Без секретов R2 — как раньше, с
напоминанием поднять latest.json.gh workflow run mirror-release.yml -f tag=mobile-v1.2.2.
Для тегов mobile-v* работает отдельная задача mirror-mobile: скачивает из
релиза только .apk, заливает, проверяет, печатает блок. К фиду десктопа она
прикоснуться не может: у неё нет ни ключа Supabase, ни манифестов
latest.yml/latest-mac.yml.latest.json в репозитории lancibleofficial/lancible-updates по-прежнему
правят руками: заменить блок "android" на напечатанный (version, url,
apk, size), блок "ios" не трогать. И url, и apk — прямая ссылка на
файл в R2: версии 1.1.1 и 1.2.0 при сбое встроенной загрузки открывают в
браузере именно url, и прямая ссылка там сразу начинает скачивание.latest.json → лендинг. Сначала файл
должен открываться по адресу в R2, и только потом на него смотрят установленные
копии (latest.json) и новые посетители (кнопка в landing/index.html).Публикация релиза на GitHub (страница «Скачать» выше, для новых
пользователей — отдельный канал от автообновления, не трогает feed
electron-updater): запушить тег vX.Y.Z — .github/workflows/release.yml
соберёт установщики на настоящих Windows- и macOS-раннерах и опубликует их
как ассеты GitHub Release (и заодно, при заданных секретах R2, зальёт файлы в R2
и фид — см. выше). Тот же workflow можно запустить вручную (Actions →
Build desktop installers → Run workflow) с тегом в поле ввода.
На этой машине у
npmесть allowlist на install-скрипты зависимостей (npm-lavamoat) — послеnpm installможет появиться предупреждениеN packages have install scripts not yet covered by allowScripts. Чинится черезnpm approve-scripts <имя-пакета>(запускает нужный скрипт и запоминает разрешение вpackage.json) — так это и было исправлено дляelectronиelectron-winstaller(нуженelectron-builder'у для сборки NSIS). Так надёжнее, чем распаковывать вручную.
yiglgfkjjvwijukdzutw, схема таблиц (profiles/projects/tasks/
sessions/user_settings, все с RLS user_id = auth.uid()) — в
supabase/schema.sql. Клиент — @supabase/supabase-js (UMD-сборка,
вендорится в src/renderer/vendor/supabase.js тем же copy-vendor.js, что и
Quill; contextIsolation не даёт использовать require() в рендерере,
поэтому подключается как обычный <script>).#account-btn), не блокирует работу офлайн.signUp() не вернул сессию сразу,
показывается экран «проверьте почту» (#auth-step-confirm) вместо
мгновенного онбординга.afterSignedIn() проверяет, есть ли уже строка в profiles для этого
user.id; если нет — онбординг, если есть — сразу вход. Это правильно
обрабатывает и случай с отложенным подтверждением email.lancible://auth-callback) и сама синхронизация данных (projects/
tasks/sessions ↔ Supabase, realtime, офлайн-очередь) — ещё не сделаны,
следующие этапы.data.json в папке пользовательских данных Electron:
%APPDATA%\Lancible\data.json (Windows). При первом запуске данные из старой
папки %APPDATA%\task-timer\ копируются автоматически (см. loadData() в
src/main.js).
Схема:
{
"projects": [{ "id", "name", "createdAt", "color": "#69d345",
"description", "pinnedAt": "..." | null }],
"tasks": [{ "id", "projectId", "title", "done", "notes": <Quill Delta|null>,
"totalMs", "rate": 3000 | null, "pinnedAt": "..." | null,
"sessions": [{ "start", "end", "ms",
"rate": 3000, // ставка на момент записи
"manual"|"recovered": true }] }],
"activeTimer": { "taskId", "startedAt", "heartbeatAt" } | null,
"ui": { "view": "home"|"project"|"calendar", "projectId", "navCollapsed": false },
"settings": { "hourlyRate": 0, "currency": "RUB", // код валюты
"theme": "system"|"light"|"dark", "lang": "ru"|"en"|"uk"|"kk" }
}
notes Delta может содержать table-атрибуты и cellBg (фон ячейки таблицы).
| Файл | Назначение |
|---|---|
src/main.js | Главный процесс: окно (свой titlebar, без меню), data.json + миграция, диалог .xlsx, синхронизация цвета кнопок окна с темой (theme:set-overlay; присланные цвета запоминаются в window-colors.json рядом с data.json, чтобы окно сразу создавалось с верной подложкой), автообновление через electron-updater (update:check/update:download/update:install). |
src/preload.js | Мост window.api (load / save / exportXlsx / copy / setTitlebarOverlay / getVersion / checkForUpdate / getUpdateStatus / downloadUpdate / installUpdate + подписки onUpdate*, onOAuthCallback, onRouteOpen). |
src/xlsx.js | Мини-генератор .xlsx (ZIP + OOXML) без зависимостей. |
src/renderer/index.html | Разметка: #titlebar (лого + поиск), #navrail (+ переключатели темы/языка), #home-view (статистика внутри .home-main, .projects-grid, #recent-section.recent-fixed), #project/calendar-view, вкладки задачи (#task-tabs/#tab-notes/#tab-history), фильтр задач в #sidebar, попапы кастомного календаря/времени (#dp-pop/#tp-pop, общие для периода в календаре и диалога записи времени), диалог подтверждения (#confirm-backdrop), #search-panel. Все статичные подписи размечены data-i18n*. Иконки — инлайн-SVG. |
src/renderer/styles.css | Стили, палитра (тёмная/светлая — CSS-переменные + [data-theme]/prefers-color-scheme), анимации, @font-face Onest. .icon — --icon цвет. |
src/renderer/app.js | Логика: i18n (словарь T, t(), pluralForm(), applyStaticTranslations(), ), (/), рейл (сворачивание — один класс , элементы вынесены в ради плавной анимации ширины), поиск из шапки, маршрутизатор видов, плитки/карусели, недавние задачи (без готовых), календарь (/, режимы month/week/day, — итог за месяц/неделю всегда в правой панели, + ), обобщённые попапы даты/времени (/, принимают anchor+value+callback — используются и календарём, и диалогом записи времени), фильтр задач по статусу (, ), вкладки задачи (), диалог подтверждения (, замена ), диалоги проекта и записи времени, меню, пины, редактор (цвет текста + таблицы + через Parchment StyleAttributor), таймер, деньги (), экспорт (заголовки тоже через ), миграция. |
cellBg#tp-pop, два прокручиваемых столбца часы/минуты, под цвета
приложения) вместо системных <input type="date">/<input type="time">.LOCALE_MAPapplyThemecycleThemebody.nav-collapsedposition:absoluteaggregateDaysrangeAggrenderViewTotalcalState.periodOnrenderPeriodSummaryopenDatePickeropenTimePickertaskFilterfilteredProjectTaskssetTaskTabconfirmDialogwindow.confirmcellBgsessionRatet()scripts/copy-vendor.js | Копирует Quill + шрифт в src/renderer/vendor/ (postinstall). |
scripts/make-icon.js | Генерирует build/icon.* из assets/logo-mark.svg (canvas + Path2D, собирает .ico через png-to-ico). |
scripts/make-logo.js | Знак Lancible: читает assets/logo-mark.svg (его же берут make-icon.js и make-mobile-icons.js), вписывает его в разметку обоих index.html и страниц лендинга и в favicon. Сторож — tests/unit/logo.test.js. |
scripts/publish-release.js | Фид автообновления: --release-base кладёт в Supabase Storage манифесты со ссылками на R2 (или GitHub), --stage раскладывает файлы для заливки в R2, без ключей — заливает всё из dist/ как есть (npm run publish:release). --mobile-apk — APK телефона: проверяет его в R2 и печатает блок "android" для latest.json, фид не трогает. |
.github/workflows/release.yml | Собирает установщики на Windows- и macOS-раннерах GitHub Actions, публикует GitHub Release (архив и страница «Скачать»), заливает файлы в Cloudflare R2 и после этого — манифесты в фид автообновления. |
.github/workflows/mirror-release.yml | Ручной запуск: переводит уже вышедший релиз на R2 (gh workflow run mirror-release.yml -f tag=v0.4.2; для APK телефона — -f tag=mobile-v1.2.2, отдельной задачей без доступа к фиду), не выпуская новую версию. |
.github/workflows/mobile-release.yml | По тегу mobile-v* собирает APK в EAS, публикует GitHub Release (архив), заливает файл в Cloudflare R2 и печатает блок "android" для latest.json. |
supabase/schema.sql | Схема БД для аккаунтов/синхронизации (таблицы + RLS-политики), выполняется вручную в SQL Editor проекта. |
scripts/smoke.js | Headless-проверка UI (npm run smoke); окно рендерера — на изолированной сессии (partition: 'nopersist:smoke'), чтобы реальная Supabase-сессия из ручных прогонов не протекала между запусками. |
scripts/xlsx-check.js | Проверка генератора .xlsx (npm run check:xlsx). |
landing/index.html | Маркетинговый лендинг (деплой на Vercel вместе с вебом: веб собирается в /app): герой, платформы и загрузки, статус проекта, возможности, раздел «Блог». Самодостаточный файл — стили и скрипты внутри. |
landing/blog-posts.js | Записи для раздела «Блог» на лендинге: массив window.LANCIBLE_POSTS (дата, тег, версия, заголовок и текст на ru/en). Новая запись добавляется в начало массива; мелкие правки и багфиксы сюда не пишем. |