Skip to content

Commit a5d0980

Browse files
Merge pull request #7 from off-grid-ai/release-core
release-core → main (0.0.26): auto-update migration, starfield, Settings accordions, Pro plan, DevTools-off
2 parents e232682 + e21cfb5 commit a5d0980

7 files changed

Lines changed: 257 additions & 75 deletions

File tree

.github/workflows/release.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,15 @@ jobs:
103103
npx electron-builder --mac \
104104
-c.dmg.artifactName='OffGrid-${version}.${ext}' \
105105
--publish always
106+
- name: Migrate legacy Pro update channel (publish pro-mac.yml)
107+
env:
108+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
109+
VERSION: ${{ needs.version.outputs.version }}
110+
run: |
111+
# Older Pro builds poll a SEPARATE channel (pro-mac.yml); the single build
112+
# now publishes only the default latest-mac.yml. Upload a copy as
113+
# pro-mac.yml (identical - same signed zip + version) so those installs see
114+
# this release, auto-update, and land on the default channel. After that
115+
# they follow latest-mac.yml. One-time bridge so no Pro user is orphaned.
116+
cp dist/latest-mac.yml dist/pro-mac.yml
117+
gh release upload "v$VERSION" dist/pro-mac.yml --clobber

e2e/tour.spec.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,20 +52,30 @@ test('Models: merged tab + use-cases + import', async () => {
5252

5353
test('Settings: setup, resource modes, storage, data & privacy all render', async () => {
5454
await nav('Settings');
55+
// Sections are collapsed accordions — the titles (headings) are always visible;
56+
// expand a card to reveal its body before asserting the body content.
5557
await expect(page.getByRole('heading', { name: 'Setup & health' })).toBeVisible();
58+
await expect(page.getByRole('heading', { name: 'Data & privacy' })).toBeVisible();
59+
60+
await page.getByRole('button', { name: /Setup & health/ }).click(); // expand
5661
await expect(page.getByText('Configure it for me')).toBeVisible();
5762
// The resource-mode selector now lives inside the Configure card.
5863
for (const m of ['Conservative', 'Balanced', 'Extreme']) {
5964
// The mode button's accessible name includes its description, so match by substring.
6065
await expect(page.getByRole('button', { name: m }).first()).toBeVisible();
6166
}
62-
await expect(page.getByRole('heading', { name: 'Data & privacy' })).toBeVisible();
67+
68+
await page.getByRole('button', { name: /Data & privacy/ }).click(); // expand
6369
await expect(page.getByText('Screen captures')).toBeVisible();
6470
await expect(page.getByText('Your data on this device')).toBeVisible();
6571
});
6672

6773
test('Resource mode is selectable (Conservative)', async () => {
74+
// Ensure the Setup & health accordion is expanded (the modes live in its body).
6875
const cons = page.getByRole('button', { name: 'Conservative' }).first();
76+
if (!(await cons.isVisible().catch(() => false))) {
77+
await page.getByRole('button', { name: /Setup & health/ }).click();
78+
}
6979
await cons.click();
7080
await expect(cons).toHaveAttribute('aria-pressed', 'true');
7181
});

src/main/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ function createWindow(): void {
8282
preload: join(__dirname, '../preload/index.js'),
8383
sandbox: false, // REQUIRED for IPC
8484
contextIsolation: true,
85-
plugins: true // Chromium's built-in PDF viewer (chat attachment viewer) needs this
85+
plugins: true, // Chromium's built-in PDF viewer (chat attachment viewer) needs this
86+
devTools: is.dev // no inspector in the packaged/production build (tamper-proofing)
8687
}
8788
})
8889

src/renderer/src/App.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { NotificationProvider, useNotifications } from './hooks/useNotifications
2323
import { ReprocessingProvider, useReprocessing } from './hooks/useReprocessing';
2424
import { useState, useEffect, useCallback, useRef } from 'react';
2525
import { GridBackdrop } from './components/ui/grid-backdrop';
26+
import { StarfieldBackdrop } from './components/ui/starfield-backdrop';
2627
import { Sidebar, SidebarBody } from './components/ui/sidebar';
2728
import { NavThemeToggle } from './components/ThemeToggle';
2829
import { motion, AnimatePresence } from 'motion/react';
@@ -562,8 +563,10 @@ function AppContent() {
562563
)}
563564
</button>
564565
)}
565-
{/* Background — flat Off Grid terminal grid (theme-aware) */}
566+
{/* Background — flat Off Grid terminal grid (theme-aware), with a dark-mode
567+
starfield + periodic shooting star layered on top. */}
566568
<GridBackdrop className="z-0" />
569+
<StarfieldBackdrop className="z-0" />
567570

568571
<div className="flex h-full relative z-10">
569572
{/* Aceternity Sidebar */}

src/renderer/src/assets/main.css

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,4 +327,51 @@ code {
327327
.actions {
328328
display: none;
329329
}
330-
}
330+
}
331+
/* Starry-night backdrop (dark mode only): a periodic emerald shooting star that
332+
streaks across the upper area, layered over the terminal grid. Static star dots
333+
live on StarfieldBackdrop; this is just the animation. Pure CSS, no deps. */
334+
@keyframes og-shooting-star {
335+
0% { transform: translate3d(0, 0, 0) rotate(32deg); opacity: 0; }
336+
4% { opacity: 1; }
337+
16% { opacity: 1; }
338+
20% { transform: translate3d(900px, 560px, 0) rotate(32deg); opacity: 0; }
339+
100% { transform: translate3d(900px, 560px, 0) rotate(32deg); opacity: 0; }
340+
}
341+
.og-shooting-star {
342+
position: absolute;
343+
top: 7%;
344+
left: 10%;
345+
width: 88px;
346+
height: 1px;
347+
background: linear-gradient(90deg, rgba(52, 211, 153, 0.9), rgba(52, 211, 153, 0));
348+
filter: drop-shadow(0 0 6px rgba(52, 211, 153, 0.45));
349+
opacity: 0;
350+
animation: og-shooting-star 12s ease-in 4s infinite;
351+
}
352+
@media (prefers-reduced-motion: reduce) {
353+
.og-shooting-star { animation: none; display: none; }
354+
}
355+
356+
/* Static star field — themeable so it reads in BOTH modes: dark dots on light,
357+
bright dots on dark. Tiled radial-gradients, repeated across the viewport. */
358+
.og-starfield {
359+
background-image:
360+
radial-gradient(1.5px 1.5px at 30px 40px, rgba(0,0,0,0.55), transparent),
361+
radial-gradient(1px 1px at 110px 90px, rgba(0,0,0,0.42), transparent),
362+
radial-gradient(1.5px 1.5px at 170px 28px, rgba(0,0,0,0.50), transparent),
363+
radial-gradient(2px 2px at 70px 158px, rgba(0,0,0,0.50), transparent),
364+
radial-gradient(1px 1px at 150px 192px, rgba(0,0,0,0.38), transparent),
365+
radial-gradient(1px 1px at 205px 120px, rgba(0,0,0,0.45), transparent);
366+
background-size: 220px 220px;
367+
background-repeat: repeat;
368+
}
369+
[data-theme="dark"] .og-starfield {
370+
background-image:
371+
radial-gradient(1.5px 1.5px at 30px 40px, rgba(255,255,255,0.95), transparent),
372+
radial-gradient(1px 1px at 110px 90px, rgba(255,255,255,0.70), transparent),
373+
radial-gradient(1px 1px at 170px 28px, rgba(255,255,255,0.85), transparent),
374+
radial-gradient(2px 2px at 70px 158px, rgba(255,255,255,0.90), transparent),
375+
radial-gradient(1px 1px at 150px 192px, rgba(255,255,255,0.60), transparent),
376+
radial-gradient(1px 1px at 205px 120px, rgba(255,255,255,0.78), transparent);
377+
}

0 commit comments

Comments
 (0)