Compare commits

..
10 Commits
Author SHA1 Message Date
talksik ca0939edf5 cleanup unused header 2026-10-04 12:04:40 -07:00
talksik 190b220391 refactor: rename window state to state 2026-10-04 12:03:48 -07:00
talksik d14436bb38 update readme 2026-10-03 15:20:59 -07:00
talksik dc1803b0fb update demo images 2026-10-03 15:15:41 -07:00
talksik ce3504816d update readme 2026-10-03 15:13:30 -07:00
talksik ee45d4a171 update readme 2026-10-03 15:11:48 -07:00
talksik 4b564bdbcb update readme copy 2026-10-03 15:06:59 -07:00
talksik 1d904afe4b update readme 2026-10-03 15:04:34 -07:00
talksik 78acace2d3 adjust for macos experience 2026-10-03 15:04:18 -07:00
talksik dae6969876 build for macos 2026-10-03 15:03:09 -07:00
13 changed files with 75 additions and 43 deletions
Vendored
BIN
View File
Binary file not shown.
+10 -9
View File
@@ -1,10 +1,11 @@
CC = cc CC = cc
CFLAGS = -g -Wall -Iinclude CFLAGS = -g -Wall -Iinclude -I/opt/homebrew/include
SOURCES = src/main.c src/window_state.c SOURCES = src/main.c src/state.c
OBJECTS = src/main.o src/window_state.o OBJECTS = src/main.o src/state.o
LDFLAGS = -lraylib -lm -lsqlite3 LDFLAGS = -L/opt/homebrew/lib
LDLIBS = -lraylib -lm -lsqlite3
HEADERS = \ HEADERS = \
include/raygui.h include/common.h include/window_state.h include/raygui.h include/common.h include/state.h
PREFIX ?= /usr/local PREFIX ?= /usr/local
BINDIR := $(PREFIX)/bin BINDIR := $(PREFIX)/bin
@@ -15,14 +16,14 @@ BINDIR := $(PREFIX)/bin
# %.o: %.c $(HEADERS) # %.o: %.c $(HEADERS)
# $(CC) $(CFLAGS) -c $< -o $@ # $(CC) $(CFLAGS) -c $< -o $@
adhd: src/main.o src/window_state.o adhd: src/main.o src/state.o
$(CC) $(CFLAGS) src/main.o src/window_state.o -o $@ $(LDFLAGS) $(CC) $(CFLAGS) src/main.o src/state.o -o $@ $(LDFLAGS) $(LDLIBS)
src/main.o: src/main.c $(HEADERS) src/main.o: src/main.c $(HEADERS)
$(CC) -c $(CFLAGS) src/main.c -o $@ $(CC) -c $(CFLAGS) src/main.c -o $@
src/window_state.o: src/window_state.c $(HEADERS) src/state.o: src/state.c $(HEADERS)
$(CC) -c $(CFLAGS) src/window_state.c -o $@ $(CC) -c $(CFLAGS) src/state.c -o $@
clean: clean:
rm -rf $(OBJECTS) adhd rm -rf $(OBJECTS) adhd
+37 -11
View File
@@ -1,14 +1,44 @@
# Flowy.adhd # Flowy.adhd
We live in a noisy digital world. Unless you turn off your WiFi, millions of companies bid for your attention as you try to perform even the simplest of tasks. We live in a noisy digital world. For anyone with adhd, doing one thing at a time is the key. NOT using fancy todo managers. Win one intention at a time instead of planning, prioritizing, and juggling 100s of things.
This tool is a free, open-source application to help you stay on track. You set an intention before you work, and an overlay will remind you of your intention every x minutes. This tool is a free, open-source application to help you stay on track. You set an intention before you work, and a big, fat overlay stays in your periphery to keep you on track.
![app](demo/app.png) ![main window](demo/main_window.png)
![desktop](demo/desktop.png) ![coding](demo/coding.png)
![research](demo/research.png)
## Install ## Install
At the moment, you must build and install the application yourself. There are minimum dependencies, so you essentially just need a C compiler. At the moment, you must build the application yourself.
Dependencies:
- raylib
- sqlite3
### macOS
```sh
brew install raylib
git clone https://git.talksik.com/FlowyLabs/adhd
cd adhd
make
./adhd
# Optional
sudo make install
```
### Linux
```sh
# Install raylib, sqlite3 according to your distro
git clone https://git.talksik.com/FlowyLabs/adhd
cd adhd
make
./adhd
# Optional
sudo make install
```
## How it works ## How it works
@@ -16,14 +46,10 @@ At the moment, you must build and install the application yourself. There are mi
2. A persistent overlay reminds you of your intention 2. A persistent overlay reminds you of your intention
3. Set whether today was a win (focused) or loss (distracted), and view your daily activity in a nice graph 3. Set whether today was a win (focused) or loss (distracted), and view your daily activity in a nice graph
## Philosophy
In a world of fancy todo managers, for anyone with adhd, doing one thing at a time is the key. Win one intention at a time instead of planning, prioritizing, and juggling 100s of things.
## Features ## Features
- **No sign in required** - **No sign in required**
- **Slick overlay to show current intention** - **Slick overlay to show current intention**
- **Lightweight** - Written in C with few dependencies, nothing bloated like electron - **Lightweight** - Written in C with few dependencies
- **Privacy first** - No telemetry, works offline - **Privacy first** - No telemetry, works offline
- **Session history** - Review your past wins and losses - **Daily history** - Keep track of which days you won or lost
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 356 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

+4 -4
View File
@@ -1,5 +1,5 @@
#ifndef WINDOWSTATE_H #ifndef STATE_H
#define WINDOWSTATE_H #define STATE_H
#include "common.h" #include "common.h"
#include <stddef.h> #include <stddef.h>
@@ -11,8 +11,8 @@ enum mode_t {
}; };
typedef enum mode_t Mode; typedef enum mode_t Mode;
void init_window_state(); void init_state();
void cleanup_window_state(); void cleanup_state();
void set_intention(char *intention); void set_intention(char *intention);
char *get_intention(); char *get_intention();
-10
View File
@@ -1,10 +0,0 @@
#include <sqlite3.h>
#include "common.h"
/* persist on disk with compact representation
date representation -> value
*/
void store_result(U32 val, struct date d);
void retrieve_result(U32 val, struct date d);
void retrieve_results_before(int *vals, struct date before);
+20 -6
View File
@@ -1,11 +1,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include <stdbool.h>
#define RAYGUI_IMPLEMENTATION #define RAYGUI_IMPLEMENTATION
#include <raygui.h> #include <raygui.h>
#include <raylib.h> #include <raylib.h>
#include "window_state.h" #include "state.h"
#include "common.h" #include "common.h"
#define WINDOW_HEIGHT 700 #define WINDOW_HEIGHT 700
@@ -18,12 +19,23 @@
void switch_mode(Mode mode) { void switch_mode(Mode mode) {
set_mode(mode); set_mode(mode);
int monitor = GetCurrentMonitor();
switch (mode) { switch (mode) {
case WINDOW: case WINDOW:
SetWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT); SetWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
SetWindowState(FLAG_WINDOW_TRANSPARENT | FLAG_WINDOW_UNDECORATED);
SetWindowOpacity(1);
// cneter in screen
SetWindowPosition((GetMonitorWidth(monitor) / 2) - (WINDOW_WIDTH / 2), (GetMonitorHeight(monitor) / 2) - (WINDOW_HEIGHT / 2));
break; break;
case OVERLAY: case OVERLAY:
SetWindowOpacity(0.5);
SetWindowSize(OVERLAY_WIDTH, OVERLAY_HEIGHT); SetWindowSize(OVERLAY_WIDTH, OVERLAY_HEIGHT);
SetWindowState(FLAG_WINDOW_TRANSPARENT | FLAG_WINDOW_UNDECORATED | FLAG_WINDOW_TOPMOST);
// bottom right of screen
SetWindowPosition(GetMonitorWidth(monitor) - OVERLAY_WIDTH, GetMonitorHeight(monitor) - OVERLAY_HEIGHT);
break; break;
default: default:
break; break;
@@ -108,11 +120,10 @@ void draw_graph(int x, int y) {
GuiDisableTooltip(); GuiDisableTooltip();
} }
bool edit_mode = false; bool edit_mode = true;
void render_window() { void render_window() {
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
DrawFPS(WINDOW_WIDTH - 50, 10);
Rectangle text_box_rect = {(WINDOW_WIDTH / 2) - 200, (WINDOW_HEIGHT / 2) - 200, 400, 50}; Rectangle text_box_rect = {(WINDOW_WIDTH / 2) - 200, (WINDOW_HEIGHT / 2) - 200, 400, 50};
Vector2 mouse_pos = GetMousePosition(); Vector2 mouse_pos = GetMousePosition();
@@ -138,9 +149,8 @@ void render_window() {
void render_overlay() { void render_overlay() {
ClearBackground(BLANK); ClearBackground(BLANK);
DrawFPS(OVERLAY_WIDTH - 50, 10);
const Rectangle button_rect = {OVERLAY_WIDTH - 100, 10, 100, 25}; const Rectangle button_rect = {OVERLAY_WIDTH - 100, OVERLAY_HEIGHT - 30, 100, 25};
int active = 0; int active = 0;
if (GuiToggleSlider(button_rect, "Toggle mode", &active)) { if (GuiToggleSlider(button_rect, "Toggle mode", &active)) {
@@ -150,6 +160,7 @@ void render_overlay() {
GuiSetStyle(DEFAULT, TEXT_SIZE, 75); GuiSetStyle(DEFAULT, TEXT_SIZE, 75);
GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_CHAR); GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, TEXT_WRAP_CHAR);
GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER); GuiSetStyle(LABEL, TEXT_ALIGNMENT, TEXT_ALIGN_CENTER);
GuiSetStyle(LABEL, TEXT_COLOR_NORMAL, ColorToInt(GOLD));
GuiLabel((Rectangle){0, 0, OVERLAY_WIDTH, OVERLAY_HEIGHT}, get_intention()); GuiLabel((Rectangle){0, 0, OVERLAY_WIDTH, OVERLAY_HEIGHT}, get_intention());
GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, 0); GuiSetStyle(DEFAULT, TEXT_WRAP_MODE, 0);
} }
@@ -159,10 +170,11 @@ int main(int argc, char *argv[]) {
localtime_r(&now, &local_time); localtime_r(&now, &local_time);
mktime(&local_time); mktime(&local_time);
init_window_state(); init_state();
printf("Welcome to Flowy.adhd\n"); printf("Welcome to Flowy.adhd\n");
SetConfigFlags(FLAG_WINDOW_TRANSPARENT | FLAG_WINDOW_UNDECORATED);
InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Flowy.adhd"); InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Flowy.adhd");
while (!WindowShouldClose()) { while (!WindowShouldClose()) {
@@ -178,5 +190,7 @@ int main(int argc, char *argv[]) {
CloseWindow(); CloseWindow();
cleanup_state();
return 0; return 0;
} }
+4 -3
View File
@@ -1,7 +1,8 @@
#include "window_state.h" #include "state.h"
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdbool.h>
#include <assert.h> #include <assert.h>
#include <sqlite3.h> #include <sqlite3.h>
@@ -100,7 +101,7 @@ static void db_get_all_records() {
assert(rc == SQLITE_OK); assert(rc == SQLITE_OK);
} }
void init_window_state() { void init_state() {
s = malloc(sizeof(struct state)); s = malloc(sizeof(struct state));
s->mode = WINDOW; s->mode = WINDOW;
@@ -169,7 +170,7 @@ static void generate_key(struct tm *time, char *buffer, size_t buffer_size) {
snprintf(buffer, buffer_size, "%d", time->tm_yday); snprintf(buffer, buffer_size, "%d", time->tm_yday);
} }
void cleanup_window_state() { void cleanup_state() {
if (!s) { if (!s) {
return; return;
} }