Chandra

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

    - Add Chandra::Store - Persistent key-value storage for Chandra apps

0.10  2026-04-02
    - Add Chandra::Shortcut - keyboard shortcuts and global hotkeys

0.09  2026-04-01
    - Fix Makefile to identify BSD's that should use GTK/WebKit2

0.08  2026-04-01
    - Fix removing unnecessary call_method overhead when calling internal XSUBS.
    - Adds Native OS desktop notifications

0.07  2026-03-31
    - Port code to XS (all methods now in C)
    - Add global css and js chain methods to Chandra::App
    - Extend routes with a way to assign custom css and js per route

0.06  2026-03-30
    - Add system tray integration and example
    - Another attempt at fixing windows to run
    - Start porting code into XS, using the INCLUDE technique

examples/form_example.pl  view on Meta::CPAN

        value => 90,
    });
});

$form->group('Notifications' => sub {
    $form->checkbox('notify_email', {
        label   => 'Email notifications',
        checked => 1,
    });

    $form->checkbox('notify_desktop', {
        label => 'Desktop notifications',
    });

    $form->radio('frequency', {
        label   => 'Digest Frequency',
        options => [
            { value => 'instant', label => 'Instant' },
            { value => 'daily',   label => 'Daily' },
            { value => 'weekly',  label => 'Weekly' },
        ],

examples/modal.pl  view on Meta::CPAN

# ── Custom modal ──────────────────────────────────────────

$app->bind('show_custom', sub {
    Chandra::Modal->show($app,
        title   => 'About This App',
        width   => 450,
        content => '<div style="text-align:center;">'
                 . '<h2 style="margin:0 0 8px;">Modal Demo</h2>'
                 . '<p style="color:var(--chandra-text-muted);">Version 1.0.0</p>'
                 . '<p>Built with <strong>Chandra</strong> &mdash; '
                 . 'a Perl desktop GUI framework.</p>'
                 . '<hr>'
                 . '<p style="font-size:0.85em;color:var(--chandra-text-muted);">'
                 . 'Modals, toasts, themes, tables, and components &mdash; all in XS.</p>'
                 . '</div>',
        buttons => [
            { label => 'Close', class => 'primary', action => 'close' },
        ],
    );
});

lib/Chandra/Form.pm  view on Meta::CPAN

    $form->hidden('csrf_token', { value => 'abc123' });

    $form->submit('Save Settings');

    # Render to HTML
    my $html = $form->render;

=head1 DESCRIPTION

Chandra::Form provides form building helpers with automatic two-way
data binding between Perl and the DOM for Chandra desktop applications.

Forms are built by chaining field methods, then rendered to HTML via
C<render()>. When used with C<Chandra::App>, the generated JavaScript
handles form submission, change events, and value synchronization
through the Chandra bridge.

=head1 METHODS

=head2 new

lib/Chandra/Notify.pm  view on Meta::CPAN

use strict;
use warnings;

# Load XS functions from Chandra bootstrap
use Chandra ();

our $VERSION = '0.25';

=head1 NAME

Chandra::Notify - Native OS desktop notifications

=head1 SYNOPSIS

    use Chandra::Notify;

    # Simple notification
    Chandra::Notify->send(
        title => 'Download Complete',
        body  => 'report.pdf has finished downloading',
    );

lib/Chandra/Notify.pm  view on Meta::CPAN

        timeout => 5000,
    );

    # Check if supported
    if (Chandra::Notify->is_supported) {
        Chandra::Notify->send(title => 'Hello', body => 'World');
    }

=head1 DESCRIPTION

Chandra::Notify provides native desktop notifications across platforms:

=over 4

=item * macOS: Uses UNUserNotificationCenter (10.15+) or NSUserNotification

=item * Linux: Uses libnotify if available, falls back to notify-send

=item * Windows: Uses toast notifications (MessageBox as fallback)

=back

lib/Chandra/Notify.pm  view on Meta::CPAN


=head1 PLATFORM NOTES

=head2 macOS

Requires macOS 10.8+ for NSUserNotification, 10.15+ for UNUserNotificationCenter.
The app must be properly signed to display notifications in some cases.

=head2 Linux

Requires a notification daemon (most desktop environments have one).
libnotify.so.4 is preferred; falls back to notify-send CLI.

=head2 Windows

Currently uses MessageBox as a fallback. Full toast notification support
is planned for a future release.

=head1 SEE ALSO

L<Chandra>, L<Chandra::App>

lib/Chandra/Pack.pm  view on Meta::CPAN

    # Create structure
    file_mkpath($lib_dir);
    file_mkpath($share);

    # AppRun
    my $apprun = file_join($app_dir, 'AppRun');
    file_spew($apprun, $self->_generate_launcher_linux());
    chmod 0755, $apprun;

    # Desktop entry
    file_spew(file_join($app_dir, lc($safe) . '.desktop'), $self->_generate_desktop());

    # Copy script
    file_copy($self->{script}, file_join($usr, 'share', 'script.pl'));

    # Copy deps
    $self->_copy_deps($lib_dir);

    # Icon
    if ($self->{icon} && file_exists($self->{icon})) {
        file_copy($self->{icon}, file_join($app_dir, lc($safe) . file_extname($self->{icon})));

lib/Chandra/Pack.pm  view on Meta::CPAN

}

sub _create_appimage {
    my ($self, $app_dir, $appimagetool) = @_;
    
    my $safe = _safe_name($self->{name});
    my $appimage_path = file_join($self->{output}, "$safe.AppImage");
    
    # Ensure proper AppDir structure
    # AppRun should already exist from build_linux
    # Ensure .desktop file is at root level
    my $desktop_file = file_join($app_dir, lc($safe) . '.desktop');
    unless (file_is_file($desktop_file)) {
        return { success => 0, error => "Missing .desktop file" };
    }
    
    # Run appimagetool
    my $cmd = "\Q$appimagetool\E \Q$app_dir\E \Q$appimage_path\E 2>&1";
    my $output = `$cmd`;
    if ($? != 0) {
        return { success => 0, error => "appimagetool failed: $output" };
    }
    
    # Make executable

lib/Chandra/Pack.pm  view on Meta::CPAN

    my ($self) = @_;
    my $perl = $self->{perl};
    return <<LAUNCHER;
\@echo off
set DIR=%~dp0
set PERL5LIB=%DIR%lib;%PERL5LIB%
"$perl" "%DIR%script.pl" %*
LAUNCHER
}

sub _generate_desktop {
    my ($self) = @_;
    my $safe = lc(_safe_name($self->{name}));
    my $icon_ext = '';
    $icon_ext = file_extname($self->{icon}) if $self->{icon} && file_exists($self->{icon});
    return <<DESKTOP;
[Desktop Entry]
Type=Application
Name=$self->{name}
Exec=./AppRun
Icon=${safe}${icon_ext}

lib/Chandra/Store.pm  view on Meta::CPAN


    # Reload picks up external changes
    $s->reload;

    # Via Chandra::App
    my $app = Chandra::App->new(title => 'My App', ...);
    my $store = $app->store;     # name derived from app title

=head1 DESCRIPTION

Chandra::Store provides persistent key-value storage for Chandra desktop
applications, backed by a JSON file at C<~/.chandra/E<lt>nameE<gt>/store.json>
by default.

Keys support dot notation for nested structures (e.g. C<window.width>).
Writes are atomic: data is written to a C<.tmp.PID> file then renamed into
place. File locking (flock) prevents corruption from concurrent processes.

=head1 METHODS

=head2 new(%args)

t/63_pack.t  view on Meta::CPAN

    my $win = $p->_generate_launcher_windows;
    like($win, qr/\@echo off/i, 'windows launcher has echo off');
    like($win, qr/PERL5LIB/, 'windows launcher sets PERL5LIB');
    like($win, qr/script\.pl/, 'windows launcher runs script.pl');
}

# ── Desktop Entry Generation ────────────────────────────────────────

{
    my $p = Chandra::Pack->new(script => $script, name => 'Test App');
    my $desktop = $p->_generate_desktop;
    like($desktop, qr/\[Desktop Entry\]/, 'desktop has header');
    like($desktop, qr/Type=Application/, 'desktop is Application type');
    like($desktop, qr/Name=Test App/, 'desktop has name');
    like($desktop, qr/Exec=\.\/AppRun/, 'desktop exec is AppRun');
}

# ── Platform Detection ───────────────────────────────────────────────

{
    my $p = Chandra::Pack->new(script => $script);
    my $plat = $p->platform;
    if ($^O eq 'darwin') {
        is($plat, 'macos', 'detects macos');
    } elsif ($^O eq 'MSWin32') {

xs/app.xs  view on Meta::CPAN

        ENTER; SAVETMPS;
        PUSHMARK(SP);
        XPUSHs(*wv_svp);
        PUTBACK;
        call_method("exit", G_DISCARD);
        FREETMPS; LEAVE;
    }
    (void)hv_stores(hv, "_started", newSViv(0));
}

 # ---- notify(%args) - send a desktop notification ----

int
notify(self, ...)
    SV *self
CODE:
{
    ChandraNotification notif;
    I32 i;

    memset(&notif, 0, sizeof(notif));



( run in 1.026 second using v1.01-cache-2.11-cpan-df04353d9ac )