Я уже давно ищу сервис для организации своего рабочего времени.
А причиной этого поиска стала вечная проблема состыковки календарей с людьми. Бывало ли у вас такое:
— Привет, давай созвонимся на час в понедельник?
— Привет, у меня в понедельник занято, давай во вторник?
— Давай, а во сколько? У меня свободно 14, 16 и 21
— Блин, у меня все это время занято, есть среда в 15
— А у меня среда вся занята…
В какой-то момент, подобные состыковки отнимали минут по 20 на одну встречу. Я уже хотел писать свой сервис, но решил загуглить. Оказалось, что их десятки разных, но почти все не умеют подключать разные календари (у меня 6 календарей из-за разных почт) либо стоят по $20+ в месяц.
Итогом моих поисков стал сервис Планерка. С ребятами я уже больше года. Меня покорило наличие Telegram-бота и API для автоматизации. Делюсь рекомендацией, потому что сам пользуюсь.
А причиной этого поиска стала вечная проблема состыковки календарей с людьми. Бывало ли у вас такое:
— Привет, давай созвонимся на час в понедельник?
— Привет, у меня в понедельник занято, давай во вторник?
— Давай, а во сколько? У меня свободно 14, 16 и 21
— Блин, у меня все это время занято, есть среда в 15
— А у меня среда вся занята…
В какой-то момент, подобные состыковки отнимали минут по 20 на одну встречу. Я уже хотел писать свой сервис, но решил загуглить. Оказалось, что их десятки разных, но почти все не умеют подключать разные календари (у меня 6 календарей из-за разных почт) либо стоят по $20+ в месяц.
Итогом моих поисков стал сервис Планерка. С ребятами я уже больше года. Меня покорило наличие Telegram-бота и API для автоматизации. Делюсь рекомендацией, потому что сам пользуюсь.
planerka.app
Планёрка — Онлайн сервис записи для экспертов: эффективное планирование встреч и управление временем
Планёрка — онлайн сервис записи, который помогает экспертам легко планировать встречи, управлять временем и сосредоточиться на главном. Удобные функции, интеграции с календарями и простота использования — всё для максимальной эффективности.
👍10❤7🤡7💩2
Сова пишет…
Открыл для себя новый тип браузера https://arc.net/ буду изучать, идея выглядит интересно
браузер с командной панелью
❤13🤡1
Аватар: Путь воды очень хорош.
Получил немалое удовольствие.
Купил билеты в премиум зал, чтобы с комфортом провести 3 часа.
Получил немалое удовольствие.
Купил билеты в премиум зал, чтобы с комфортом провести 3 часа.
👍19🤡7💯1
За 10 минут я дошел только до кальция.
Мусорный Магний конечно очень мешает
http://dimiwww.tg-me.com/Fe26/
Мусорный Магний конечно очень мешает
http://dimiwww.tg-me.com/Fe26/
🤡6👍2🤯1
Создание контента отнимает много времени. Сколько вы готовы платить за подписку на кучу контента по эффектору и фронтенду?
Anonymous Poll
20%
5€
18%
3€
11%
1€
51%
0€
🤡20👍10
Нажмите на кнопку ниже, чтобы настроить регулярные донаты.
Если подключиться к боту не удается, используйте эту ссылку.
Если подключиться к боту не удается, используйте эту ссылку.
Я увидел пожелание организовать сборы на контент, но не делать часть его платным.
Не уверен, что такая модель мне подходит, так как видел довольно скудные результаты, когда пробовал организовать подобные сборы ранее.
Но если очень хочется задонатить на публичный контент, пожалуйста, ссылка выше.
Не уверен, что такая модель мне подходит, так как видел довольно скудные результаты, когда пробовал организовать подобные сборы ранее.
Но если очень хочется задонатить на публичный контент, пожалуйста, ссылка выше.
🤡9👍7👎1🔥1
Когда стоит использовать
Довольно часто возникает ситуация, когда в компоненте нужно выбрать значение из списка по идентификатору приходящему в props.
Не стоит использовать в таких случаях useEffect или useMemo. Гораздо эффективнее и нагляднее здесь будет работать
Его главная задача — выбрать значение из стора основываясь на параметре извне. Самый важный параметр здесь —
Всё, что передано в параметр
Если значение в списке
Иногда внутри fn создается и возвращается новый объект, а значит простое сравнение по ссылке (
Кстати,
#effector
useStoreMap
Довольно часто возникает ситуация, когда в компоненте нужно выбрать значение из списка по идентификатору приходящему в props.
Не стоит использовать в таких случаях useEffect или useMemo. Гораздо эффективнее и нагляднее здесь будет работать
useStoreMap
.Его главная задача — выбрать значение из стора основываясь на параметре извне. Самый важный параметр здесь —
keys
, это примерно то же самое, что и dependencies в стандартных хуках useEffect, useMemo.Всё, что передано в параметр
keys
, придет вторым аргументом в fn
. Так можно сделать функцию fn чистой без завязки на замыкание, хоть выноси как редюссер в отдельный файл.Если значение в списке
keys
поменяется, то функция fn будет вызвана еще раз. Только если fn
возвращает другой результат, будет перерендер. Это крайне выгодно, если store часто обновляется, но вычисленное значение остается тем же самым.Иногда внутри fn создается и возвращается новый объект, а значит простое сравнение по ссылке (
===
) будет всегда false
, в этом случае стоит переопределить параметр updateFilter
, в котором нужно описать сравнение старого и нового состояния. Можно не сравнивать все поля объектов, а например сравнить только идентификатор или хеш.Кстати,
defaultValue
и updateFilter
— не обязательные параметры. Жмите ⚡️ если узнали что-то новое.#effector
⚡83🔥6👍4🫡2❤1
Еще один пример использования
Как бы часто не менялась роль в сторе
Очень удобно, с точки зрения оптимизации рендеринга. Это все еще самая дорогая часть рантайма в React.
#effector
useStoreMap
Как бы часто не менялась роль в сторе
$role
, перерендер компонента произойдет только когда результат функции fn
вернет новое значение. То есть роль станет подходящей или наоборот неподходящей.Очень удобно, с точки зрения оптимизации рендеринга. Это все еще самая дорогая часть рантайма в React.
#effector
👍22⚡6🔥2🥰1
А использовать подобный компонент можно например вот так.
Мне очень нравится, когда компонент и его props со значениями читаются как предложение.
#effector
Мне очень нравится, когда компонент и его props со значениями читаются как предложение.
#effector
👍32
Давайте подведем итоги 2022 года! (Спасибо, за репост)
Final Results
11%
У меня все отлично, даже лучше чем представлялось
9%
Все хорошо, цели достигнуты, минимум стресса
36%
Средне, как обычно, что-то хорошо, что-то упущено, стресса хватило
26%
Мало что доведено до конца, излишняя тревога, многие планы сорваны
18%
Ужасно, постоянный стресс, невозможно что-либо планировать, когда это закончится
🫡4🍾1
Как работает общение между процессами в Electron.
Я не хотел делать по типичным советам из гайда Electron. Они еще рекомендуют сделать специальную прослойку через файл
В
В
Одинаковые импорты важны, ведь в настройках сборки я прохожусь по файлам процессов main и renderer с помощью babel. Я просто вписал импорты выше в factories в
Теперь у каждого запроса созданного через createRequest будет свой уникальный sid. И благодаря общей конфигурации компилятора и сборщика для обеих частей electron сиды будут идентичны. Имя эффекта просто поможет его явно идентифицировать в логах отладки.
В следующем посте я покажу как использовать эти запросы в renderer и main процессах. Жмите ⚡️ если узнали что-то новое.
#effector #electron
Я не хотел делать по типичным советам из гайда Electron. Они еще рекомендуют сделать специальную прослойку через файл
preload.js
, мне было лень, но даже его можно автоматизировать по примеру, который я покажу.В
ipc/factory.ts
я создал домен и функцию создающую запросы. Создаю запросы не через домен, чтобы не было соблазна навесить обработчик сразу при создании эффекта. Плюс, так визуально можно разделить обычные эффекты и запросы.В
ipc/db.ts
я собственно описываю эти запросы, главное тут это типы и sid. Чтобы все заработало, потребовалось добавить алиасы для @ipc/db
и @ipc/factory
, это нужно, чтобы из main процесса (nodejs) и renderer (chrome) можно было импортировать эти файлы одинаково.Одинаковые импорты важны, ведь в настройках сборки я прохожусь по файлам процессов main и renderer с помощью babel. Я просто вписал импорты выше в factories в
effector/babel-plugin
. Можно было использовать swc, но мне как-то привычнее babel. Я использовал vite-plugin-electron, чтобы собирать обе части приложения.Теперь у каждого запроса созданного через createRequest будет свой уникальный sid. И благодаря общей конфигурации компилятора и сборщика для обеих частей electron сиды будут идентичны. Имя эффекта просто поможет его явно идентифицировать в логах отладки.
В следующем посте я покажу как использовать эти запросы в renderer и main процессах. Жмите ⚡️ если узнали что-то новое.
#effector #electron
⚡16👍2🔥1
Подсоединяю логику обработки запросов в electron.
Модуль
Для идентификации запросов используется как раз таки
По этой же причине, запросы лежат в отдельной директории ipc в корне проекта и туда же настроены алиасы. Путь к файлам с запросами идентичен в обеих системах сборки.
На самом деле, можно добавить рантайм валидацию данных, например с помощью runtypes. Если интересно, покажу как это сделать, жмите 💯. Но структурно ничего не поменяется, лишь появится новый код внутри
В файле
Схема обработки запроса из renderer процесса будет выглядеть как-то так:
1. renderer вызывает
2. событие попадает в
3. когда эффект завершает своё выполнение, ответ возвращается обратно renderer-процессу
Функция
#effector #electron
Модуль
ipc-requests.ts
добавляет обработчики всем запросам созданным через createRequest
. В данном случае, я слушаю сообщения по каналу ipcMain. Метод .handle
позволяет дождаться выполнения асинхронного кода и отправить результат обратно в renderer процесс.Для идентификации запросов используется как раз таки
.sid
. Если для renderer и main процесса будут разные компиляторы и системы сборки, крайне важно удостовериться, что юниты получают идентичные sid'ы.По этой же причине, запросы лежат в отдельной директории ipc в корне проекта и туда же настроены алиасы. Путь к файлам с запросами идентичен в обеих системах сборки.
На самом деле, можно добавить рантайм валидацию данных, например с помощью runtypes. Если интересно, покажу как это сделать, жмите 💯. Но структурно ничего не поменяется, лишь появится новый код внутри
.onCreateEffect
.В файле
ipc-database.ts
я добавляю хендлеры для всех запросов из @ipc/db
. Можно было бы сделать специальный TS-тип, чтобы иметь гарантии, что все запросы получили хендлеры, но я решил сделать проще, для наглядности.Схема обработки запроса из renderer процесса будет выглядеть как-то так:
1. renderer вызывает
invoke('@ipc:${fx.sid}', { params })
2. событие попадает в
ipc-requests.ts
, который вызывает соответствующий эффект3. когда эффект завершает своё выполнение, ответ возвращается обратно renderer-процессу
Функция
addHandlers
из модуля ipc-database вызывается при инициализации, я вынес её отдельно, чтобы было удобно "подсовывать" нужную ссылку на базу данных. Я хочу еще в рантайме менять соединение с SQLite базой.#effector #electron
💯10⚡1👍1🔥1
Использование запросов в renderer процессе
А теперь осталось обработать вызов эффекта внутри
Самое важное на строке 9 — вызов .invoke, который дождется ответа от процесса
Использовать эти запросы, можно ровно так же, как и любые другие.
#effector #electron
А теперь осталось обработать вызов эффекта внутри
createRequest
. Но будем это делать ровно так же через domain.onCreateEffect. Большая часть кода здесь — подготовка данных и обработка ответа. Самое важное на строке 9 — вызов .invoke, который дождется ответа от процесса
ipcMain
. Я хотел сделать более прозрачную систему ответов, поэтому заворачиваю ответ в main процессе в try/catch. Но это не обязательно.Note: If the handler in the main process throws an error, the promise returned by invoke will reject. However, the Error object in the renderer process will not be the same as the one thrown in the main process.
Использовать эти запросы, можно ровно так же, как и любые другие.
#effector #electron
🔥5