Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,36 @@ sudo ninja install
io.github.alainm23.planify
```

### 🍏 macOS Build (Experimental)
Planify can be built on macOS (tested on Apple Silicon, macOS 14+) using Homebrew’s GTK4/libadwaita stack. Optional components not available on macOS are disabled (Evolution, WebKit, portals, spell check).

1. Install dependencies:
```bash
brew update
brew install vala meson ninja gtk4 libadwaita libgee json-glib \
libsoup sqlite libical gtksourceview5 desktop-file-utils \
libsecret icu4c pango cairo fontconfig
```
2. Make pkg-config find libical/icu:
```bash
export PKG_CONFIG_PATH="/opt/homebrew/opt/libical/lib/pkgconfig:/opt/homebrew/opt/icu4c/lib/pkgconfig:$PKG_CONFIG_PATH"
```
3. Build and run via the helper script:
```bash
chmod +x run-macos.sh
./run-macos.sh
GSETTINGS_SCHEMA_DIR=data ./build/src/io.github.alainm23.planify
```
The script cleans the build dir, configures Meson with macOS-safe flags (`-Devolution=false -Dwebkit=false -Dportal=false -Dspelling=disabled`), compiles, compiles schemas, and launches the app with the needed runtime env vars.

#### DMG Packaging (Experimental)
After building, you can generate a DMG (still relies on Homebrew GTK/libadwaita on the target system; not fully standalone):
```bash
# From repo root, after ./run-macos.sh
./scripts/build-macos-dmg.sh
```
Result: `build/Planify.dmg`.

### 🏗️ Development Setup

**Using GNOME Builder:**
Expand Down
13 changes: 12 additions & 1 deletion core/Services/Database.vala
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,15 @@ public class Services.Database : GLib.Object {
return _instance;
}

private string get_db_dir () {
// On macOS prefer the standard Application Support location instead of XDG
if (FileUtils.test ("/System/Library/CoreServices", FileTest.IS_DIR)) {
return Path.build_filename (Environment.get_home_dir (), "Library", "Application Support", "io.github.alainm23.planify");
}

return Path.build_filename (Environment.get_user_data_dir (), "io.github.alainm23.planify");
}

construct {
table_columns["Attachments"] = new Gee.ArrayList<string> ();
table_columns["Attachments"].add ("id");
Expand Down Expand Up @@ -176,7 +185,9 @@ public class Services.Database : GLib.Object {
}

public void init_database () {
db_path = Environment.get_user_data_dir () + "/io.github.alainm23.planify/database.db";
var db_dir = get_db_dir ();
DirUtils.create_with_parents (db_dir, 0755);
db_path = Path.build_filename (db_dir, "database.db");
Sqlite.Database.open (db_path, out db);

create_tables ();
Expand Down
3 changes: 2 additions & 1 deletion core/Utils/Util.vala
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ public class Util : GLib.Object {
string _css = """
popover,
window {
font-size: %s%;
font-size: %s%%;
}
""";

Expand All @@ -365,6 +365,7 @@ public class Util : GLib.Object {
try {
string scale = (100 * Services.Settings.get_default ().get_double ("font-scale")).to_string ();
var css = _css.printf (scale);
print ("CSS Font Scale Applied: %s\n", css);

provider.load_from_string (css);
Gtk.StyleContext.add_provider_for_display (
Expand Down
Binary file added data/.DS_Store
Binary file not shown.
Binary file added data/gschemas.compiled
Binary file not shown.
1 change: 1 addition & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pkgconfig = import('pkgconfig')

add_global_arguments('-DGETTEXT_PACKAGE="@0@"'.format (meson.project_name()), language:'c')
add_project_arguments('-DLIBICAL_GLIB_UNSTABLE_API=1', language: 'c')
add_project_arguments('--vapidir', meson.project_source_root() / 'vapi', language: 'vala')

gio_dep = dependency('gio-2.0')
glib_dep = dependency('glib-2.0')
Expand Down
58 changes: 58 additions & 0 deletions run-macos.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash

# Script to build and run Planify on macOS without optional dependencies

# Check critical dependencies
echo "Checking dependencies..."
for dep in pango cairo fontconfig; do
if ! brew list $dep &>/dev/null; then
echo "Installing $dep..."
brew install $dep
fi
done

# Clean previous build if exists
if [ -d "build" ]; then
echo "Cleaning previous build..."
rm -rf build
fi

# Ensure pkg-config can find Homebrew libs (libical, icu4c)
export PKG_CONFIG_PATH="/opt/homebrew/opt/libical/lib/pkgconfig:/opt/homebrew/opt/icu4c/lib/pkgconfig:${PKG_CONFIG_PATH}"

# Configure with meson without optional dependencies
echo "Configuring project..."
meson setup build \
-Dwebkit=false \
-Dspelling=disabled \
-Dportal=false \
-Devolution=false \
-Dgxml-0.20:docs=false

# Compile
echo "Compiling..."
if meson compile -C build; then
# Compile gschemas locally
echo "Compiling gschemas..."
glib-compile-schemas data

# Run with environment variables for schemas
echo "Running Planify..."
echo ""

# Configure Pango and Cairo for macOS
export FONTCONFIG_PATH=/opt/homebrew/etc/fonts
export FONTCONFIG_FILE=/opt/homebrew/etc/fonts/fonts.conf
export XDG_DATA_DIRS=/opt/homebrew/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}

# Use macOS system fonts as fallback
export PANGO_EMOJI_FONT="Apple Color Emoji"

# Force app to appear in Dock on macOS
export GDK_BACKEND=quartz

GSETTINGS_SCHEMA_DIR=data ./build/src/io.github.alainm23.planify
else
echo "Compilation error"
exit 1
fi
83 changes: 83 additions & 0 deletions scripts/build-macos-dmg.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/bin/bash
# Package Planify into a minimal macOS .app bundle and DMG (experimental).
# Assumes you've already built with ./run-macos.sh and have ./build artifacts.

set -euo pipefail

ROOT="$(cd "$(dirname "$0")/.." && pwd)"
BUILD="$ROOT/build"
DESTDIR="$BUILD/dist"
APPDIR="$BUILD/Planify.app"
DMG="$BUILD/Planify.dmg"
BIN_NAME="io.github.alainm23.planify"

if [ ! -x "$BUILD/src/$BIN_NAME" ]; then
echo "Planify binary not found in $BUILD/src. Run ./run-macos.sh first." >&2
exit 1
fi

echo "Staging install to $DESTDIR..."
meson install -C "$BUILD" --destdir "$DESTDIR"

echo "Building app bundle at $APPDIR..."
rm -rf "$APPDIR"
mkdir -p "$APPDIR/Contents/MacOS" "$APPDIR/Contents/Resources"

# Main binary and wrapper
cp "$DESTDIR/opt/homebrew/bin/$BIN_NAME" "$APPDIR/Contents/MacOS/planify-bin"
cat > "$APPDIR/Contents/MacOS/Planify" <<'EOF'
#!/bin/bash
APP_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
RES="$APP_ROOT/Resources"
export GSETTINGS_SCHEMA_DIR="$RES/glib-2.0/schemas"
export XDG_DATA_DIRS="$RES:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
export FONTCONFIG_PATH=/opt/homebrew/etc/fonts
export FONTCONFIG_FILE=/opt/homebrew/etc/fonts/fonts.conf
export PANGO_EMOJI_FONT="Apple Color Emoji"
exec "$APP_ROOT/MacOS/planify-bin" "$@"
EOF
chmod +x "$APPDIR/Contents/MacOS/Planify"

# Resources (schemas/icons/locale/etc.)
cp -R "$DESTDIR/opt/homebrew/share/." "$APPDIR/Contents/Resources/"
glib-compile-schemas "$APPDIR/Contents/Resources/glib-2.0/schemas"

# Bundle Planify libs (not fully self-contained; still uses Homebrew GTK stack)
cp "$DESTDIR/opt/homebrew/lib/libplanify.0.dylib" "$APPDIR/Contents/MacOS/"

# Find and copy libgxml from Homebrew (it's an external dependency)
GXML_LIB=$(find /opt/homebrew/lib -name "libgxml-0.20.*.dylib" -type f | head -1)
if [ -z "$GXML_LIB" ]; then
echo "Warning: libgxml not found in /opt/homebrew/lib. App may not work properly." >&2
else
GXML_NAME=$(basename "$GXML_LIB")
cp "$GXML_LIB" "$APPDIR/Contents/MacOS/"
echo "Bundled $GXML_NAME"

# Update library paths
install_name_tool -change "/opt/homebrew/lib/$GXML_NAME" "@executable_path/$GXML_NAME" "$APPDIR/Contents/MacOS/libplanify.0.dylib" 2>/dev/null || true
fi

install_name_tool -change /opt/homebrew/lib/libplanify.0.dylib @executable_path/libplanify.0.dylib "$APPDIR/Contents/MacOS/planify-bin"
install_name_tool -id @executable_path/libplanify.0.dylib "$APPDIR/Contents/MacOS/libplanify.0.dylib"

# Info.plist with version from the build config
VERSION="$(grep -E 'public const string VERSION' "$BUILD/config.vala" | sed 's/.*\"\\(.*\\)\";/\\1/')" || VERSION="0.0.0"
cat > "$APPDIR/Contents/Info.plist" <<PLIST
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>CFBundleExecutable</key><string>Planify</string>
<key>CFBundleIdentifier</key><string>io.github.alainm23.planify</string>
<key>CFBundleName</key><string>Planify</string>
<key>CFBundleVersion</key><string>${VERSION}</string>
<key>CFBundleShortVersionString</key><string>${VERSION}</string>
<key>LSMinimumSystemVersion</key><string>11.0</string>
<key>NSHighResolutionCapable</key><true/>
</dict></plist>
PLIST

echo "Creating DMG at $DMG..."
rm -f "$DMG"
hdiutil create -volname "Planify" -srcfolder "$APPDIR" -ov -format UDZO "$DMG"
echo "Done: $DMG"
23 changes: 23 additions & 0 deletions src/App.vala
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,27 @@ public class Planify : Adw.Application {
add_action (snooze_60);
}

private static void ensure_schema_dir () {
var current = GLib.Environment.get_variable ("GSETTINGS_SCHEMA_DIR");
if (current != null && current != "") {
return;
}

// Prefer a locally built schema (for in-tree runs), then fall back to the system install dir.
string[] candidates = {
Path.build_filename (GLib.Environment.get_current_dir (), "data"),
Path.build_filename (Build.DATADIR, "glib-2.0", "schemas")
};

foreach (var dir in candidates) {
var compiled = Path.build_filename (dir, "gschemas.compiled");
if (FileUtils.test (compiled, FileTest.IS_REGULAR)) {
GLib.Environment.set_variable ("GSETTINGS_SCHEMA_DIR", dir, true);
break;
}
}
}

public static int main (string[] args) {
#if USE_WEBKITGTK
// NOTE: Workaround for https://github.com/alainm23/planify/issues/1069
Expand All @@ -227,6 +248,8 @@ public class Planify : Adw.Application {
GLib.Environment.set_variable ("WEBKIT_DISABLE_DMABUF_RENDERER", "1", true);
#endif

ensure_schema_dir ();

Planify app = Planify.instance;
return app.run (args);
}
Expand Down
Loading
Loading