Clean up shit
This commit is contained in:
169
lib/main.dart
169
lib/main.dart
@@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io'; // Required for Platform check
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:system_tray/system_tray.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
@@ -8,8 +7,7 @@ import 'package:audioplayers/audioplayers.dart';
|
||||
|
||||
// --- Configuration ---
|
||||
const Duration popupInterval = Duration(hours: 1); // How often to pop up
|
||||
const String notificationSound =
|
||||
'notification.wav'; // Sound file in assets/sounds/
|
||||
const String notificationSound = 'MeetTheSniper.ogg';
|
||||
// --------------------
|
||||
|
||||
void main() async {
|
||||
@@ -37,64 +35,89 @@ void main() async {
|
||||
class JournalerApp extends StatelessWidget {
|
||||
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
|
||||
static final ThemeData lightTheme = ThemeData(
|
||||
brightness: Brightness.light,
|
||||
primarySwatch: Colors.blue, // Or use ColorScheme.fromSeed(seedColor: Colors.blue)
|
||||
static final ThemeData lightTheme = ThemeData.light().copyWith(
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
scaffoldBackgroundColor: Colors.grey[100], // Slightly off-white
|
||||
appBarTheme: const AppBarTheme(
|
||||
backgroundColor: Colors.blue,
|
||||
foregroundColor: Colors.white, // Title and icons
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: Colors.blue,
|
||||
brightness: Brightness.light,
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
border: const OutlineInputBorder(),
|
||||
scaffoldBackgroundColor: Colors.grey[100],
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: Colors.blue,
|
||||
foregroundColor: Colors.white,
|
||||
titleTextStyle: _baseTitleTextStyle.copyWith(color: Colors.white),
|
||||
),
|
||||
inputDecorationTheme: _baseInputDecorationTheme.copyWith(
|
||||
focusedBorder: OutlineInputBorder(
|
||||
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
|
||||
static final ThemeData darkTheme = ThemeData(
|
||||
brightness: Brightness.dark,
|
||||
primarySwatch: Colors.blue, // Keep blue, or choose a different shade
|
||||
// Or use ColorScheme.fromSeed(seedColor: Colors.blue, brightness: Brightness.dark)
|
||||
static final ThemeData darkTheme = ThemeData.dark().copyWith(
|
||||
visualDensity: VisualDensity.adaptivePlatformDensity,
|
||||
scaffoldBackgroundColor: Colors.grey[900], // Dark background
|
||||
appBarTheme: AppBarTheme(
|
||||
backgroundColor: Colors.grey[850], // Darker app bar
|
||||
foregroundColor: Colors.white, // Title and icons
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: Colors.blue,
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
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(
|
||||
borderSide: BorderSide(color: Colors.grey), // Lighter border for dark theme
|
||||
borderSide: BorderSide(color: Colors.grey), // Dark theme default border
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.blue.shade300, width: 2.0),
|
||||
),
|
||||
labelStyle: TextStyle(color: Colors.grey[400]), // Lighter label for dark theme
|
||||
// Ensure content padding is applied if needed, or use default
|
||||
// contentPadding: const EdgeInsets.all(8.0), // This was in TextField, maybe move to theme?
|
||||
labelStyle: _baseInputDecorationTheme.labelStyle?.copyWith(
|
||||
color: Colors.grey[400],
|
||||
),
|
||||
),
|
||||
// Ensure text field text color is readable
|
||||
textTheme: const TextTheme(
|
||||
bodyMedium: TextStyle(color: Colors.white), // Default text style
|
||||
// Define other text styles as needed
|
||||
textTheme: _baseTextTheme.copyWith(
|
||||
// Ensure body text is readable on dark background
|
||||
bodyMedium: _baseTextTheme.bodyMedium?.copyWith(color: Colors.white),
|
||||
// Optionally override other dark theme text styles here
|
||||
),
|
||||
// Define icon theme for app bar if needed, though foregroundColor often handles it
|
||||
// iconTheme: const IconThemeData(color: Colors.white),
|
||||
);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'Journaler',
|
||||
theme: lightTheme, // Use the light theme definition
|
||||
darkTheme: darkTheme, // Use the dark theme definition
|
||||
themeMode: ThemeMode.system, // Automatically switch based on system settings
|
||||
theme: lightTheme,
|
||||
darkTheme: darkTheme,
|
||||
themeMode: ThemeMode.system,
|
||||
home: const MainPage(),
|
||||
debugShowCheckedModeBanner: false,
|
||||
);
|
||||
@@ -109,7 +132,6 @@ class MainPage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MainPageState extends State<MainPage> with WindowListener {
|
||||
// final AppWindow _appWindow = AppWindow(); // REMOVED - Not used
|
||||
final SystemTray _systemTray = SystemTray();
|
||||
final AudioPlayer _audioPlayer = AudioPlayer();
|
||||
|
||||
@@ -167,8 +189,7 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
||||
Future<void> _initSystemTray() async {
|
||||
// Use simple relative paths for assets declared in pubspec.yaml
|
||||
// The build process handles packaging these assets correctly.
|
||||
String iconPath =
|
||||
Platform.isWindows ? 'assets/app_icon.ico' : 'assets/app_icon.png';
|
||||
String iconPath = 'assets/app_icon.ico';
|
||||
|
||||
// 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.
|
||||
@@ -200,35 +221,28 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
||||
// Handle system tray menu item clicks
|
||||
_systemTray.registerSystemTrayEventHandler((eventName) {
|
||||
debugPrint("System Tray Event: $eventName");
|
||||
if (eventName == kSystemTrayEventClick) {
|
||||
_showWindow();
|
||||
} else if (eventName == kSystemTrayEventRightClick) {
|
||||
// Optional: Show a context menu on right click
|
||||
// _systemTray.popUpContextMenu() - need to define menu items first
|
||||
}
|
||||
_showWindow();
|
||||
});
|
||||
}
|
||||
|
||||
// --- Periodic Popup & Sound --- //
|
||||
void _startPopupTimer() {
|
||||
_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 {
|
||||
bool isVisible = await windowManager.isVisible();
|
||||
if (!isVisible) {
|
||||
bool wasVisible = await windowManager.isVisible();
|
||||
if (!wasVisible) {
|
||||
// Ensure size and position before showing
|
||||
await windowManager.setSize(const Size(1600, 900)); // Set desired size
|
||||
await windowManager.center(); // Center the window
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
// Play sound ONLY when window becomes visible
|
||||
await _playSound();
|
||||
} else {
|
||||
// If already visible, just bring to front and 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
|
||||
}
|
||||
|
||||
// --- 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
|
||||
Future<void> _setWindowConfig() async {
|
||||
// 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(
|
||||
appBar: AppBar(
|
||||
title: const Text('Journaler'),
|
||||
// Optional: Add a save button or other actions
|
||||
actions: [
|
||||
IconButton(
|
||||
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',
|
||||
),
|
||||
actions: const [
|
||||
// Remove all buttons
|
||||
// No actions needed anymore
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
@@ -341,6 +354,10 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
||||
maxLines: null, // Allows unlimited lines
|
||||
expands: true, // Fills the available space
|
||||
readOnly: true, // Make it non-editable
|
||||
style:
|
||||
Theme.of(
|
||||
context,
|
||||
).textTheme.bodyMedium, // Apply theme text style
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Previous Entry',
|
||||
// border: OutlineInputBorder(), // Handled by theme
|
||||
@@ -356,6 +373,10 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
||||
maxLines: null,
|
||||
expands: true,
|
||||
autofocus: true, // Focus here when window appears
|
||||
style:
|
||||
Theme.of(
|
||||
context,
|
||||
).textTheme.bodyMedium, // Apply theme text style
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Current Entry (What\'s on your mind?)',
|
||||
// border: OutlineInputBorder(), // Handled by theme
|
||||
@@ -377,14 +398,18 @@ class _MainPageState extends State<MainPage> with WindowListener {
|
||||
controller: _todoController,
|
||||
maxLines: null,
|
||||
expands: true,
|
||||
style:
|
||||
Theme.of(
|
||||
context,
|
||||
).textTheme.bodyMedium, // Apply theme text style
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Todo List',
|
||||
// border: OutlineInputBorder(), // Handled by theme
|
||||
// contentPadding: EdgeInsets.all(8.0), // Handled by theme or default
|
||||
),
|
||||
onChanged: (text) {
|
||||
// Optional: Auto-save Todo list changes
|
||||
// Consider debouncing if saving frequently
|
||||
// Auto-save Todo list changes (consider debouncing)
|
||||
_saveTodoList();
|
||||
},
|
||||
),
|
||||
),
|
||||
|
Reference in New Issue
Block a user