Аннотация

Статья о том: как мне пришла в голову идея создать настольное приложение на electron и node.js для отображения картин известных художников как обои рабочего стола; с какими трудностями столкнулся; как решал процесс сборки приложения на node.js для конечного пользователя.

Введение

В прошлом году я подписался на одно сообщество во ВК, суть его была в том, что он выкладывал каждый день посты, которые содержали 2 единственные вещи: изображение какой-либо академической картины и краткая информация о ней (автор и дата). Я подписался и через некоторое время мне пришла в голову идея, что было бы здорово, если каждый день запуская свой компьютер, я бы наблюдал те же вещи, что и посты в сообществе. Идея томилась довольно долго, но через некоторое время я решил, что всё таки сделаю его. Я не эксперт в настольных приложениях и операционных системах, но основные принципы их работы были осознаны мной при обучении в университете. В данный момент занимаю позицию старшего веб-разработчика в компании, занимающейся разработкой системы предиктивной видеоаналитики.

Цель

Перед тем как начать что-либо делать, надо задуматься над целью, которую будут достигать ваши действия. Это один из фундаментальных моментов в любой деятельности. Было решено, что приложение должно приносить пользователю эстетическое удовольствие, показывая прекрасные картины сотворенные руками человека. Запоминать их таким образом возможно, но это не самое эффективное занятие с точки зрения траты времени. Если хочется проникнуться  искусством, будет гораздо эффективнее ходить на лекции, в музеи, читать соответствующие статьи и быть в кругу людей, которым это интересно.

Таким образом, цель — доставление пользователю эстетического удовольствия через показ картин на рабочем столе.

Исходные данные

Исходные данные для работы разрабатываемого ПО 

  • конфигурация, предоставленная пользователем после запуска приложения;

  • данные о картинах

Упаковка node.js приложения в исполняемый файл

Изначально javascript представлял из себя скриптовый язык, который исполняется в браузере на виртуальной машине. Со временем он развивался и смог переместиться на серверную сторону, где очень активно используется, по большей части из под docker‑а. Но до node.js@v20 (её не было на момент написания приложения) не существовало нативного способа создать исполняемый файл из .js файла, поэтому предполагается использовать стороннее решение — pkg.

Что такое обои рабочего стола?

Рассмотрим на примере Windows. Сама ОС система имеет набор методов Win32 API, которые доступны для пользователя. Для того, чтобы пользователь взаимодействовал с ОС была придумана промежуточная программа решающая эту проблему — Windows Explorer. Именно он занимается отображением папок, отображает меню Windows снизу на экране и некоторое изображение, которое и является обоями на рабочем столе. Таким образом задача состоит в том, чтобы научиться её менять.

Для наглядности попробуйте в «Диспетчере задач» найти службу «Проводник» и перезапустить ее. В момент перезагрузки на месте заставки рабочего стола окажется черный экран.

Способы программной установки обоев рабочего стола

Из предыдущего раздела следует, что если какой либо ЯП может взаимодействовать с API ОС, то скорее всего он сможет программно поменять обои рабочего стола. javascript не является подобным языком, поэтому кажется логичным вызвать стороннюю программу из процесса node.js и использовать для смены обоев её. Было найдено решение при котором для каждой из ОС был бы написан отдельный сценарий.

Первым претендентом стал PowerShell-скрипт для Windows, найденных на просторах интернета.

param([string]$imgPath="c:\wallpapers\1.jpg")
$code = @'
using System.Runtime.InteropServices;
namespace Win32 {
public class Wallpaper {
[DllImport("user32.dll", CharSet=CharSet.Auto)]
static extern int SystemParametersInfo (int uAction , int uParam , string lpvParam , int fuWinIni) ;
public static void SetWallpaper(string thePath) {
SystemParametersInfo(20,0,thePath,3);
}
}
}
'@

С помощью метода SystemParametersInfo скрипт устанавливает обои, но имеет критический недостаток — работает нестабильно, иногда каждый раз, а иногда его необходимо перезапускать до 20 раз чтобы сценарий действительно установил обои.

Делать самописные скрипты оказалось довольно проблемно, ведь есть 3 ОС и у каждой множество версий, поэтому было принято решение найти готовую библиотеку, которая бы поддерживала данный функционал. В NPM была обнаружена отличная библиотека wallpaper уже с полностью реализованным функционалом. Для использования достаточно вызвать метод setWallpaper(imageUrl) и обои будут установлены. Проблема выбора программы для установки обоев на этом этапе была решена.

Требования

Функциональные требования

Хоть вся работа и реализуется только автором статьи, будет лучше сначала собрать требования, которые были бы понятны любому человеку знакомому с ПК, а уже затем детализировать их, всё более раскрывая все нюансы.

В результате был сформирован небольшой список требований, которому должно будет соответствовать приложение:

  • приложение должно легко устанавливаться на ПК пользователя

  • конфигурируемость, пользователь может

    • включать интервальный показ картин

    • выключать интервальный показ картин

    • изменять длительность интервала

    • выбирать авторов, картины которых будут демонстрироваться

  • приложение должно запускаться автоматически при старте ПК

Уточнение требований

  • приложение должно быть собрано в один или несколько исполняемых файлов и доступно для скачивания пользователем с какого-либо интернет ресурса

  • конфигурация приложения должно осуществляться посредством пользовательского интерфейса

    • необходим элемент управления для включения и выключения приложения

    • необходим элемент управления для настройки интервала показа картин

    • необходим элемент управления для выбора показываемых авторов

  • приложение осуществляет запуск после перезагрузки или включения компьютера автоматически, без участия пользователя

Архитектура

Первичная архитектура

Из требований можно сделать вывод, что приложение можно разделить на две основные части: пользовательский интерфейс (клиент) и непосредственно ту, что будет изменять фоновое изображение рабочего стола пользователя (сервер). Вывод — можно применить стандартную клиент-серверную архитектуру.

Клиент нужно собрать в настольное приложение, а сервер сделать исполняемым файлом. Есть нюанс чтобы устанавливать обои через какой-то интервал, нужно чтобы сервер был запущен всё время использования ПК. Следовательно, нужно установить его как сервис на уровне ОС. На рис. можно увидеть в квадратно-стрелочной нотации архитектуру на наиболее абстрактном уровне, не привязанном к технологиям.

Рис.
Рис. Принцип работы приложения

Вторичная архитектура

Итоговый вариант можно увидеть на рисунке ниже. Приложение состоит их двух частей: первая-клиент Angular-а собранный в электрон приложение (исполняемый файл) и сервер (WallpaperChanger), который точно также собран в исполняемый файл и установлен в системе как служба.

Рис. Архитектура приложения
Рис. Архитектура приложения

Процесс реализации

На этом этапе всё относительно стандартно:

Создание UI. Интерфейс состоит из одной формы, содержащий три элемента управления, селектор выбора интервала смены обоев, кнопку сохранить и включение/выключение приложения. Выполнено с помощью библиотеки компонентов Taiga.UI от классных ребят из Тинькофф. Использовать библиотеки компонентов для такого маленького приложения это чрезмерно, но дизайн и DX слишком хорош, чтобы не использовать её в своих pet-проектах.

Создание сервера. Типичный  Nest.js — сервер изменяющий конфигурацию. Теоретически можно было сделать хранение данных в обычном текстовом файле, но как задел на будущее был взята легкая СУБД sqlite.

Критическая проблема

В dev режиме приложение работало отлично, однако при сборке по какой-то причине выбрасывалась ошибка — невозможно создать процесс. Библиотека не может установить обои. Для объяснение ошибки достаточно немного углубиться в принцип её работы. Для Linux библиотека просто вызывает некоторые системные команды с помощью bash-а, однако для Windows и OSX она использует предварительно скомпилированные исполняемые файлы, которые написаны на Rust и Swift соответственно. То на чем они написаны не играет роли, поскольку в результате это просто исполняемый файл. И именно эти исполняемые файлы pkg не мог упаковать в результирующий бандл. Никакие флаги pkg для сборки не имели эффекта. 

В данный момент было потрачено много усилий поэтому было решено взять небольшую паузу. Это о том, как важно иногда посмотреть на задачу со свежим взглядом. Снова было перечитано нарушаемое условие — серверное приложение должно работать без предварительно установленной node.js. И тут пришло озарение, можно не собирать приложение в исполняемый файл, а просто положить исходники и интерпретатор node.js рядом, и вызывать его с флагом –entry, который указывает исходный запускаемый файл. Проблема решена.

Скриншоты пользовательского интерфейса

Рис. Пользовательский интерфейс приложения
Рис. Пользовательский интерфейс приложения
Рис. Изображение обоев после установки на рабочий стол
Рис. Изображение обоев после установки на рабочий стол
Рис. Еще одно пример работы приложения
Рис. Еще одно пример работы приложения

Заключение

В результате получилось работающее приложение, которое может менять обои рабочего стола с некоторой периодичностью. Я остался очень доволен.

После завершения работы, оказалось что навыков программирования для решения этой задачи оказалось мало, необходимо было гибко мыслить, чтобы обходить проблемы. Создать через CLI приложение и запустить его было просто, проблемой оказалось сделать так чтобы это работало для такого узкого кейса.

Это крайне полезный навык, поскольку в работе зачастую не хватает именно его. Специально развивать его не стоит, потому что он слишком недетерминированный, однако можно с уверенностью сказать, что изучение Computer Science в широком смысле поможет его развить.

Спасибо за внимание.

Ссылки

https://github.com/40oleg/Museum

Комментарии (4)


  1. khromova1
    17.07.2024 11:04

    Это похвально, но уже есть многое наподобие этого


  1. m03r
    17.07.2024 11:04
    +2

    Было бы по-настоящему здорово не перереализовывать уже имеющийся как минимум в Windows и macOS функционал (десять лет назад у меня винда прекрасно меняла обои автоматом — там были разные раскрашенные фрагменты множества Мандельброта), а написать, допустим, кроссплатформенную утилиту, которая эти системные настройки выставляет унифицированно, например. Закинул список URL, а он тебе все их скачал и поставил в ротацию средствами системы. И обновляет ещё периодически, когда новые картины появляются.

    Ну и отдельное количество недоумение — Electron. Тащить целый браузер ради того, чтобы просто продублировать системный функционал...

    Но хорошо, что удалось поупражняться в реализации своих идей, этого не отнять.


    1. Aleus1249355
      17.07.2024 11:04
      +1

      Не совсем так, там целый браузер для этого маленького GUI


      1. johny_cat
        17.07.2024 11:04
        +1

        К слову, если не хочется тянуть целый браузер, а веб подёргать надо, можно использовать софт который тянет за собой не браузер, а веб-вью например tauri или wails. Да и вроде была библиотека которая позволяла паковать нативные файлы для использования вместе с pkg, сейчас правда не вспомню как она называется. Но в целом для экспериментов можно использовать электрон, ничего страшного в этом нет.