Skip to content
Merged
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
Empty file removed .github/workflows/.gitkeep
Empty file.
44 changes: 44 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Build

on:
push:
branches: [main, khesir/dev]
pull_request:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-android:
name: Build Android
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'

- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.35.4'
channel: 'stable'
cache: true

- name: Get dependencies
run: flutter pub get

- name: Build APK
run: |
flutter build apk --release \
--dart-define="PROD=true" \
--dart-define="SUPABASE_URL=${{ secrets.SUPABASE_URL }}" \
--dart-define="SUPABASE_ANON_KEY=${{ secrets.SUPABASE_ANON_KEY }}" \
--dart-define="GOOGLE_WEB_CLIENT_ID=${{ secrets.GOOGLE_WEB_CLIENT_ID }}"

102 changes: 102 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: Release

on:
push:
tags:
- 'v*'

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-android:
name: Build Android
runs-on: ubuntu-latest
environment: production
steps:
- uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'

- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.35.4'
channel: 'stable'
cache: true

- name: Get dependencies
run: flutter pub get

- name: Extract version from tag
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

- name: Build APK
run: |
flutter build apk --release \
--dart-define="PROD=true" \
--dart-define="SUPABASE_URL=${{ secrets.SUPABASE_URL }}" \
--dart-define="SUPABASE_ANON_KEY=${{ secrets.SUPABASE_ANON_KEY }}" \
--dart-define="GOOGLE_WEB_CLIENT_ID=${{ secrets.GOOGLE_WEB_CLIENT_ID }}"

- name: Build App Bundle
run: |
flutter build appbundle --release \
--dart-define="PROD=true" \
--dart-define="SUPABASE_URL=${{ secrets.SUPABASE_URL }}" \
--dart-define="SUPABASE_ANON_KEY=${{ secrets.SUPABASE_ANON_KEY }}" \
--dart-define="GOOGLE_WEB_CLIENT_ID=${{ secrets.GOOGLE_WEB_CLIENT_ID }}"

- name: Rename artifacts
run: |
mv build/app/outputs/flutter-apk/app-release.apk build/app/outputs/flutter-apk/KeepTrack-${{ steps.version.outputs.VERSION }}.apk
mv build/app/outputs/bundle/release/app-release.aab build/app/outputs/bundle/release/KeepTrack-${{ steps.version.outputs.VERSION }}.aab

- name: Upload APK artifact
uses: actions/upload-artifact@v4
with:
name: android-apk
path: build/app/outputs/flutter-apk/KeepTrack-${{ steps.version.outputs.VERSION }}.apk

- name: Upload AAB artifact
uses: actions/upload-artifact@v4
with:
name: android-aab
path: build/app/outputs/bundle/release/KeepTrack-${{ steps.version.outputs.VERSION }}.aab

create-release:
name: Create GitHub Release
runs-on: ubuntu-latest
needs: [build-android]
permissions:
contents: write
steps:
- name: Extract version from tag
id: version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts

- name: Display downloaded files
run: ls -R artifacts

- name: Create Release
uses: softprops/action-gh-release@v2
with:
name: Keep Track v${{ steps.version.outputs.VERSION }}
draft: true
generate_release_notes: true
files: |
artifacts/android-apk/*.apk
artifacts/android-aab/*.aab
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5 changes: 5 additions & 0 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ android {
ndkVersion = flutter.ndkVersion

compileOptions {
isCoreLibraryDesugaringEnabled = true
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
Expand Down Expand Up @@ -42,3 +43,7 @@ android {
flutter {
source = "../.."
}

dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
}
19 changes: 19 additions & 0 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

<!-- Notifications -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>
<uses-permission android:name="android.permission.VIBRATE"/>

<application
android:label="Keep Track"
android:name="${applicationName}"
Expand Down Expand Up @@ -34,6 +40,19 @@
<meta-data
android:name="flutterEmbedding"
android:value="2" />

<!-- Boot receiver for rescheduling notifications after device restart -->
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>

<!-- Notification receiver -->
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
</application>
<!-- Required to query activities that can process text, see:
https://developer.android.com/training/package-visibility and
Expand Down
15 changes: 8 additions & 7 deletions installers/desktop_inno_script.iss
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
; Non-commercial use only

#define MyAppName "Keep Track"
#define MyAppVersion "7.3"
#define MyAppName "KeepTrack"
#define MyAppVersion "0.7.4"
#define MyAppPublisher "Khesir"
#define MyAppURL "https://khesir.com"
#define MyAppURL "https://keep-track.khesir.com/"
#define MyAppExeName "keep_track.exe"

[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{A1C21F3D-EFFE-4448-B387-C9D8414C7960}
AppId={{A8947B06-4B99-45BB-8600-8A7D4B7D06D1}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
Expand All @@ -33,10 +33,10 @@ DisableProgramGroupPage=yes
; Uncomment the following line to run in non administrative install mode (install for current user only).
;PrivilegesRequired=lowest
OutputDir=C:\Users\ajriz\Documents\Projects\Personal-Codex\personal_codex\installers
OutputBaseFilename=KeepTrack-v.7.3
OutputBaseFilename=KeepTrack-v0.7.4
SetupIconFile=C:\Users\ajriz\Documents\Projects\Personal-Codex\personal_codex\app_icon.ico
SolidCompression=yes
WizardStyle=modern
WizardStyle=modern dynamic

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
Expand All @@ -46,9 +46,10 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{

[Files]
Source: "C:\Users\ajriz\Documents\Projects\Personal-Codex\personal_codex\build\windows\x64\runner\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Users\ajriz\Documents\Projects\Personal-Codex\personal_codex\build\windows\x64\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Users\ajriz\Documents\Projects\Personal-Codex\personal_codex\build\windows\x64\runner\Release\app_links_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Users\ajriz\Documents\Projects\Personal-Codex\personal_codex\build\windows\x64\runner\Release\flutter_windows.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Users\ajriz\Documents\Projects\Personal-Codex\personal_codex\build\windows\x64\runner\Release\permission_handler_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Users\ajriz\Documents\Projects\Personal-Codex\personal_codex\build\windows\x64\runner\Release\url_launcher_windows_plugin.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Users\ajriz\Documents\Projects\Personal-Codex\personal_codex\build\windows\x64\runner\Release\data\*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs createallsubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

Expand Down
5 changes: 5 additions & 0 deletions ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,10 @@
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>remote-notification</string>
</array>
</dict>
</plist>
22 changes: 18 additions & 4 deletions landing/.vitepress/theme/components/DownloadButtons.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
target="_blank"
rel="noopener noreferrer"
>
<span class="download-icon">{{ getIcon(asset.name) }}</span>
<span class="download-icon" v-html="getIcon(asset.name)"></span>
<span>{{ getLabel(asset.name) }}</span>
<span class="size">{{ formatSize(asset.size) }}</span>
</a>
Expand Down Expand Up @@ -81,9 +81,13 @@ onMounted(async () => {
})

function getIcon(filename: string): string {
if (filename.includes('windows') || filename.endsWith('.exe')) return '🪟'
if (filename.includes('android') || filename.endsWith('.apk')) return '🤖'
return '📦'
if (filename.includes('windows') || filename.endsWith('.exe')) {
return '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M0 3.449L9.75 2.1v9.451H0m10.949-9.602L24 0v11.4H10.949M0 12.6h9.75v9.451L0 20.699M10.949 12.6H24V24l-12.9-1.801"/></svg>'
}
if (filename.includes('android') || filename.endsWith('.apk')) {
return '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M17.523 15.341c-.5 0-.91-.41-.91-.91s.41-.91.91-.91.91.41.91.91-.41.91-.91.91m-11.046 0c-.5 0-.91-.41-.91-.91s.41-.91.91-.91.91.41.91.91-.41.91-.91.91m11.4-6.044l1.994-3.455a.416.416 0 00-.152-.567.416.416 0 00-.568.152L17.12 8.93c-1.54-.7-3.27-1.09-5.12-1.09s-3.58.39-5.12 1.09L4.85 5.427a.416.416 0 00-.568-.152.416.416 0 00-.152.567l1.994 3.455C2.64 11.185 0 14.613 0 18.545h24c0-3.932-2.64-7.36-6.123-9.248"/></svg>'
}
return '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor"><path d="M20 6h-8l-2-2H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2z"/></svg>'
}

function getLabel(filename: string): string {
Expand Down Expand Up @@ -121,4 +125,14 @@ function formatSize(bytes: number): string {
opacity: 0.8;
font-weight: 400;
}

.download-icon {
display: flex;
align-items: center;
}

.download-icon :deep(svg) {
width: 24px;
height: 24px;
}
</style>
8 changes: 4 additions & 4 deletions landing/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ Personal Codex is a comprehensive desktop application designed to help you manag
- Focus sessions with automatic breaks
- Statistics and insights

### 🌙 Modern Interface
- Beautiful, clean design
- Full dark mode support
- Responsive layout for all screen sizes
### 🔔 Mobile Notifications
- Push notifications on Android and iOS
- Task deadline reminders
- Payment and finance alerts

### 🔐 Secure & Private
- Supabase authentication
Expand Down
13 changes: 8 additions & 5 deletions landing/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ layout: home
hero:
name: Keep Track
tagline: Your all-in-one personal management system
text: Organize your life with powerful task management, comprehensive finance tracking, and productivity tools - all in one beautiful app.
text: Manage tasks, track finances, and boost productivity — all in one app.
image:
src: /app_icon.png
alt: Keep Track App
actions:
- theme: brand
text: Download Now
Expand All @@ -26,10 +29,6 @@ features:
title: Pomodoro Timer
details: Boost your productivity with built-in Pomodoro timer. Focus on your work with timed sessions and automatic break reminders.

- icon: 📊
title: Beautiful Dashboard
details: Get insights at a glance with our modern, clean dashboard. Track your tasks, finances, and productivity in real-time.

- icon: 🌙
title: Dark Mode
details: Easy on the eyes with full dark mode support. Switch between light and dark themes seamlessly across all screens.
Expand All @@ -46,6 +45,10 @@ features:
title: Modern Design
details: Built with Flutter and Material Design 3. Beautiful, responsive, and intuitive interface inspired by modern design principles.

- icon: 🔔
title: Mobile Notifications
details: Stay on top of your tasks and finances with push notifications on Android and iOS. Never miss a deadline or payment reminder.

- icon: 🚀
title: Regular Updates
details: Constantly improving with new features and bug fixes. Check out our GitHub releases for the latest updates.
Expand Down
Binary file added landing/public/app_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions lib/core/config/app_info.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/// Application information and configuration
class AppInfo {
AppInfo._();

/// GitHub repository owner
static const String gitHubOwner = 'khesir';

/// GitHub repository name
static const String gitHubRepo = 'KeepTrack';

/// Full GitHub repository path
static String get gitHubRepoPath => '$gitHubOwner/$gitHubRepo';

/// Primary download URL for app updates
static const String downloadUrl = 'https://keep-track.khesir.com/download';

/// GitHub releases URL (fallback)
static String get releasesUrl =>
'https://github.com/$gitHubOwner/$gitHubRepo/releases';

/// GitHub API URL for latest release
static String get latestReleaseApiUrl =>
'https://api.github.com/repos/$gitHubOwner/$gitHubRepo/releases/latest';
}
12 changes: 12 additions & 0 deletions lib/core/migrations/migration_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ import 'migrations/039_create_pomodoro_sessions_table.dart';
import 'migrations/040_add_pomodoro_session_pause_and_project.dart';
import 'migrations/041_cleanup_stale_pomodoro_sessions.dart';
import 'migrations/042_add_pomodoro_session_title.dart';
import 'migrations/043_create_buckets_table.dart';
import 'migrations/044_add_bucket_id_to_task_and_project.dart';
import 'migrations/045_add_pomodoro_stopwatch_type.dart';
import 'migrations/046_add_debt_monthly_payment_fields.dart';
import 'migrations/047_add_goal_fee_fields.dart';
import 'migrations/048_add_fee_to_payment_rpcs.dart';

/// Manages database migrations
///
Expand Down Expand Up @@ -297,6 +303,12 @@ class MigrationManager {
Migration040AddPomodoroSessionPauseAndProject(),
Migration041CleanupStalePomodoroSessions(),
Migration042AddPomodoroSessionTitle(),
Migration043CreateBucketsTable(),
Migration044AddBucketIdToTaskAndProject(),
Migration045AddPomodoroStopwatchType(),
Migration046AddDebtMonthlyPaymentFields(),
Migration047AddGoalFeeFields(),
Migration048AddFeeToPaymentRpcs(),
// Add new migrations here:
];

Expand Down
Loading
Loading