Clean up shit
This commit is contained in:
167
lib/main.dart
167
lib/main.dart
@@ -1,5 +1,4 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:io'; // Required for Platform check
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:system_tray/system_tray.dart';
|
import 'package:system_tray/system_tray.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
@@ -8,8 +7,7 @@ import 'package:audioplayers/audioplayers.dart';
|
|||||||
|
|
||||||
// --- Configuration ---
|
// --- Configuration ---
|
||||||
const Duration popupInterval = Duration(hours: 1); // How often to pop up
|
const Duration popupInterval = Duration(hours: 1); // How often to pop up
|
||||||
const String notificationSound =
|
const String notificationSound = 'MeetTheSniper.ogg';
|
||||||
'notification.wav'; // Sound file in assets/sounds/
|
|
||||||
// --------------------
|
// --------------------
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
@@ -37,64 +35,89 @@ void main() async {
|
|||||||
class JournalerApp extends StatelessWidget {
|
class JournalerApp extends StatelessWidget {
|
||||||
const JournalerApp({super.key});
|
const JournalerApp({super.key});
|
||||||
|
|
||||||
|
// --- Base Theme Configuration ---
|
||||||
|
static final TextTheme _baseTextTheme = const TextTheme(
|
||||||
|
bodyMedium: TextStyle(fontSize: 24),
|
||||||
|
// Define other common styles if needed
|
||||||
|
);
|
||||||
|
|
||||||
|
static final TextStyle _baseTitleTextStyle = const TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
);
|
||||||
|
|
||||||
|
static final InputDecorationTheme
|
||||||
|
_baseInputDecorationTheme = const InputDecorationTheme(
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
labelStyle: TextStyle(fontSize: 20), // Base label size
|
||||||
|
// contentPadding: EdgeInsets.all(12.0), // Example: Add padding globally
|
||||||
|
);
|
||||||
|
// ------------------------------
|
||||||
|
|
||||||
// Define the light theme
|
// Define the light theme
|
||||||
static final ThemeData lightTheme = ThemeData(
|
static final ThemeData lightTheme = ThemeData.light().copyWith(
|
||||||
brightness: Brightness.light,
|
|
||||||
primarySwatch: Colors.blue, // Or use ColorScheme.fromSeed(seedColor: Colors.blue)
|
|
||||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||||
scaffoldBackgroundColor: Colors.grey[100], // Slightly off-white
|
colorScheme: ColorScheme.fromSeed(
|
||||||
appBarTheme: const AppBarTheme(
|
seedColor: Colors.blue,
|
||||||
backgroundColor: Colors.blue,
|
brightness: Brightness.light,
|
||||||
foregroundColor: Colors.white, // Title and icons
|
|
||||||
),
|
),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
scaffoldBackgroundColor: Colors.grey[100],
|
||||||
border: const OutlineInputBorder(),
|
appBarTheme: AppBarTheme(
|
||||||
|
backgroundColor: Colors.blue,
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
titleTextStyle: _baseTitleTextStyle.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
inputDecorationTheme: _baseInputDecorationTheme.copyWith(
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.blue.shade600, width: 2.0),
|
borderSide: BorderSide(color: Colors.blue.shade600, width: 2.0),
|
||||||
),
|
),
|
||||||
labelStyle: TextStyle(color: Colors.grey[700]),
|
labelStyle: _baseInputDecorationTheme.labelStyle?.copyWith(
|
||||||
|
color: Colors.grey[700],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
textTheme: _baseTextTheme.copyWith(
|
||||||
|
// Optionally override specific light theme text styles here
|
||||||
),
|
),
|
||||||
// Add other theme properties like textTheme if needed
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Define the dark theme
|
// Define the dark theme
|
||||||
static final ThemeData darkTheme = ThemeData(
|
static final ThemeData darkTheme = ThemeData.dark().copyWith(
|
||||||
brightness: Brightness.dark,
|
|
||||||
primarySwatch: Colors.blue, // Keep blue, or choose a different shade
|
|
||||||
// Or use ColorScheme.fromSeed(seedColor: Colors.blue, brightness: Brightness.dark)
|
|
||||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||||
scaffoldBackgroundColor: Colors.grey[900], // Dark background
|
colorScheme: ColorScheme.fromSeed(
|
||||||
appBarTheme: AppBarTheme(
|
seedColor: Colors.blue,
|
||||||
backgroundColor: Colors.grey[850], // Darker app bar
|
brightness: Brightness.dark,
|
||||||
foregroundColor: Colors.white, // Title and icons
|
|
||||||
),
|
),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
scaffoldBackgroundColor: Colors.grey[900],
|
||||||
|
appBarTheme: AppBarTheme(
|
||||||
|
backgroundColor: Colors.grey[850],
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
titleTextStyle: _baseTitleTextStyle.copyWith(color: Colors.white),
|
||||||
|
),
|
||||||
|
inputDecorationTheme: _baseInputDecorationTheme.copyWith(
|
||||||
border: const OutlineInputBorder(
|
border: const OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.grey), // Lighter border for dark theme
|
borderSide: BorderSide(color: Colors.grey), // Dark theme default border
|
||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderSide: BorderSide(color: Colors.blue.shade300, width: 2.0),
|
borderSide: BorderSide(color: Colors.blue.shade300, width: 2.0),
|
||||||
),
|
),
|
||||||
labelStyle: TextStyle(color: Colors.grey[400]), // Lighter label for dark theme
|
labelStyle: _baseInputDecorationTheme.labelStyle?.copyWith(
|
||||||
// Ensure content padding is applied if needed, or use default
|
color: Colors.grey[400],
|
||||||
// contentPadding: const EdgeInsets.all(8.0), // This was in TextField, maybe move to theme?
|
|
||||||
),
|
),
|
||||||
// Ensure text field text color is readable
|
|
||||||
textTheme: const TextTheme(
|
|
||||||
bodyMedium: TextStyle(color: Colors.white), // Default text style
|
|
||||||
// Define other text styles as needed
|
|
||||||
),
|
),
|
||||||
// Define icon theme for app bar if needed, though foregroundColor often handles it
|
textTheme: _baseTextTheme.copyWith(
|
||||||
// iconTheme: const IconThemeData(color: Colors.white),
|
// Ensure body text is readable on dark background
|
||||||
|
bodyMedium: _baseTextTheme.bodyMedium?.copyWith(color: Colors.white),
|
||||||
|
// Optionally override other dark theme text styles here
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
title: 'Journaler',
|
title: 'Journaler',
|
||||||
theme: lightTheme, // Use the light theme definition
|
theme: lightTheme,
|
||||||
darkTheme: darkTheme, // Use the dark theme definition
|
darkTheme: darkTheme,
|
||||||
themeMode: ThemeMode.system, // Automatically switch based on system settings
|
themeMode: ThemeMode.system,
|
||||||
home: const MainPage(),
|
home: const MainPage(),
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
);
|
);
|
||||||
@@ -109,7 +132,6 @@ class MainPage extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MainPageState extends State<MainPage> with WindowListener {
|
class _MainPageState extends State<MainPage> with WindowListener {
|
||||||
// final AppWindow _appWindow = AppWindow(); // REMOVED - Not used
|
|
||||||
final SystemTray _systemTray = SystemTray();
|
final SystemTray _systemTray = SystemTray();
|
||||||
final AudioPlayer _audioPlayer = AudioPlayer();
|
final AudioPlayer _audioPlayer = AudioPlayer();
|
||||||
|
|
||||||
@@ -167,8 +189,7 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
|||||||
Future<void> _initSystemTray() async {
|
Future<void> _initSystemTray() async {
|
||||||
// Use simple relative paths for assets declared in pubspec.yaml
|
// Use simple relative paths for assets declared in pubspec.yaml
|
||||||
// The build process handles packaging these assets correctly.
|
// The build process handles packaging these assets correctly.
|
||||||
String iconPath =
|
String iconPath = 'assets/app_icon.ico';
|
||||||
Platform.isWindows ? 'assets/app_icon.ico' : 'assets/app_icon.png';
|
|
||||||
|
|
||||||
// IMPORTANT: You need to create an icon file named app_icon.ico (for Windows)
|
// IMPORTANT: You need to create an icon file named app_icon.ico (for Windows)
|
||||||
// and/or app_icon.png (for Mac/Linux) and place it in the 'assets/' directory.
|
// and/or app_icon.png (for Mac/Linux) and place it in the 'assets/' directory.
|
||||||
@@ -200,35 +221,28 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
|||||||
// Handle system tray menu item clicks
|
// Handle system tray menu item clicks
|
||||||
_systemTray.registerSystemTrayEventHandler((eventName) {
|
_systemTray.registerSystemTrayEventHandler((eventName) {
|
||||||
debugPrint("System Tray Event: $eventName");
|
debugPrint("System Tray Event: $eventName");
|
||||||
if (eventName == kSystemTrayEventClick) {
|
|
||||||
_showWindow();
|
_showWindow();
|
||||||
} else if (eventName == kSystemTrayEventRightClick) {
|
|
||||||
// Optional: Show a context menu on right click
|
|
||||||
// _systemTray.popUpContextMenu() - need to define menu items first
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Periodic Popup & Sound --- //
|
// --- Periodic Popup & Sound --- //
|
||||||
void _startPopupTimer() {
|
void _startPopupTimer() {
|
||||||
_popupTimer = Timer.periodic(popupInterval, (timer) {
|
_popupTimer = Timer.periodic(popupInterval, (timer) {
|
||||||
_showWindowAndPlaySound();
|
// Timer now only requests the window to show
|
||||||
|
_showWindow();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _showWindowAndPlaySound() async {
|
|
||||||
await _showWindow();
|
|
||||||
await _playSound();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _showWindow() async {
|
Future<void> _showWindow() async {
|
||||||
bool isVisible = await windowManager.isVisible();
|
bool wasVisible = await windowManager.isVisible();
|
||||||
if (!isVisible) {
|
if (!wasVisible) {
|
||||||
// Ensure size and position before showing
|
// Ensure size and position before showing
|
||||||
await windowManager.setSize(const Size(1600, 900)); // Set desired size
|
await windowManager.setSize(const Size(1600, 900)); // Set desired size
|
||||||
await windowManager.center(); // Center the window
|
await windowManager.center(); // Center the window
|
||||||
await windowManager.show();
|
await windowManager.show();
|
||||||
await windowManager.focus();
|
await windowManager.focus();
|
||||||
|
// Play sound ONLY when window becomes visible
|
||||||
|
await _playSound();
|
||||||
} else {
|
} else {
|
||||||
// If already visible, just bring to front and focus
|
// If already visible, just bring to front and focus
|
||||||
await windowManager.focus();
|
await windowManager.focus();
|
||||||
@@ -287,6 +301,19 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
|||||||
// _currentEntryController.clear(); // Decide if you want to clear it immediately
|
// _currentEntryController.clear(); // Decide if you want to clear it immediately
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- Add a specific save function for Todo List --- //
|
||||||
|
void _saveTodoList() {
|
||||||
|
// TODO: Implement debounced logic to save the todo list
|
||||||
|
// Avoid saving on every single keystroke - use a debounce mechanism
|
||||||
|
// (e.g., wait 500ms after the last change before saving)
|
||||||
|
String todoList = _todoController.text;
|
||||||
|
print("Saving Todo list (placeholder)... [${todoList.length} chars]");
|
||||||
|
// --- Your actual todo list persistence logic goes here ---
|
||||||
|
// Example:
|
||||||
|
// await saveTodoListToFile(todoList);
|
||||||
|
// --------------------------------------------------------
|
||||||
|
}
|
||||||
|
|
||||||
// Helper to set initial window config like aspect ratio
|
// Helper to set initial window config like aspect ratio
|
||||||
Future<void> _setWindowConfig() async {
|
Future<void> _setWindowConfig() async {
|
||||||
// Wait a moment to ensure window manager is fully ready after init
|
// Wait a moment to ensure window manager is fully ready after init
|
||||||
@@ -303,23 +330,9 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Journaler'),
|
title: const Text('Journaler'),
|
||||||
// Optional: Add a save button or other actions
|
actions: const [
|
||||||
actions: [
|
// Remove all buttons
|
||||||
IconButton(
|
// No actions needed anymore
|
||||||
icon: const Icon(Icons.save),
|
|
||||||
onPressed: _saveData,
|
|
||||||
tooltip: 'Save Current Entry & Todo',
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.volume_up),
|
|
||||||
onPressed: _playSound, // For testing sound
|
|
||||||
tooltip: 'Test Sound',
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Icons.timer),
|
|
||||||
onPressed: _showWindowAndPlaySound, // For testing popup
|
|
||||||
tooltip: 'Test Popup',
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
@@ -341,6 +354,10 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
|||||||
maxLines: null, // Allows unlimited lines
|
maxLines: null, // Allows unlimited lines
|
||||||
expands: true, // Fills the available space
|
expands: true, // Fills the available space
|
||||||
readOnly: true, // Make it non-editable
|
readOnly: true, // Make it non-editable
|
||||||
|
style:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).textTheme.bodyMedium, // Apply theme text style
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Previous Entry',
|
labelText: 'Previous Entry',
|
||||||
// border: OutlineInputBorder(), // Handled by theme
|
// border: OutlineInputBorder(), // Handled by theme
|
||||||
@@ -356,6 +373,10 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
|||||||
maxLines: null,
|
maxLines: null,
|
||||||
expands: true,
|
expands: true,
|
||||||
autofocus: true, // Focus here when window appears
|
autofocus: true, // Focus here when window appears
|
||||||
|
style:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).textTheme.bodyMedium, // Apply theme text style
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Current Entry (What\'s on your mind?)',
|
labelText: 'Current Entry (What\'s on your mind?)',
|
||||||
// border: OutlineInputBorder(), // Handled by theme
|
// border: OutlineInputBorder(), // Handled by theme
|
||||||
@@ -377,14 +398,18 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
|||||||
controller: _todoController,
|
controller: _todoController,
|
||||||
maxLines: null,
|
maxLines: null,
|
||||||
expands: true,
|
expands: true,
|
||||||
|
style:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).textTheme.bodyMedium, // Apply theme text style
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Todo List',
|
labelText: 'Todo List',
|
||||||
// border: OutlineInputBorder(), // Handled by theme
|
// border: OutlineInputBorder(), // Handled by theme
|
||||||
// contentPadding: EdgeInsets.all(8.0), // Handled by theme or default
|
// contentPadding: EdgeInsets.all(8.0), // Handled by theme or default
|
||||||
),
|
),
|
||||||
onChanged: (text) {
|
onChanged: (text) {
|
||||||
// Optional: Auto-save Todo list changes
|
// Auto-save Todo list changes (consider debouncing)
|
||||||
// Consider debouncing if saving frequently
|
_saveTodoList();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Reference in New Issue
Block a user