devbox setup, dep upgrades, lint fixes, Android build fixes

- Add devbox.json pinning Flutter 3.35.7, Android SDK (Nix flake),
  openjdk17, just, openssl
- Add android/nix-android-sdk/ Nix flake + flake.lock + Android Studio
  config script
- Add justfile with build/get/upgrade/icons/analyze/rebuild recipes
- flutter pub upgrade --major-versions: file_picker ^11, google_fonts ^8,
  permission_handler ^12, share_plus ^12, flutter_lints ^6 (+71 transitive)
- Fix file_picker v11 API: FilePicker.platform → FilePicker.getDirectoryPath()
- Fix all 37 analyzer issues: deprecated APIs (window, WillPopScope, Share,
  SvgPicture color), async BuildContext guards, key constructors, private
  createState() return types, unused locals, print → debugPrint, etc.
- Hook _handleCommand into onSubmitted for : prefix commands
- Android: Gradle 8.3→8.11.1, AGP 8.2.2→8.9.1, KGP 1.8.22→2.2.20,
  compileSdk/targetSdk 34→36, namespace auto-derivation for library modules,
  kotlin.compiler.execution.strategy=in-process

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
randogoth 2026-06-19 17:08:29 +03:00
parent 9dbd638fa8
commit fc6c69db24
19 changed files with 1287 additions and 383 deletions

56
lib/note_editor.dart Normal file → Executable file
View file

@ -6,6 +6,7 @@ import 'package:flutter_markdown_latex/flutter_markdown_latex.dart';
import 'package:flutter_svg/svg.dart';
import 'package:markdown/markdown.dart' as md;
import 'package:shared_preferences/shared_preferences.dart';
import 'package:share_plus/share_plus.dart';
import 'themes/day.dart';
import 'themes/night.dart';
import 'themes/markdown.dart';
@ -16,13 +17,15 @@ class NoteEditorScreen extends StatefulWidget {
final String? notesDirectoryPath; // Add this
final bool isDarkMode;
NoteEditorScreen(
{required this.note,
required this.isDarkMode,
required this.notesDirectoryPath});
const NoteEditorScreen({
super.key,
required this.note,
required this.isDarkMode,
required this.notesDirectoryPath,
});
@override
_NoteEditorScreenState createState() => _NoteEditorScreenState();
State<NoteEditorScreen> createState() => _NoteEditorScreenState();
}
class _NoteEditorScreenState extends State<NoteEditorScreen> {
@ -59,7 +62,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
try {
_initialContent = await widget.note.readAsString();
} catch (e) {
print("❌ Failed to read file: ${widget.note.path}");
debugPrint("❌ Failed to read file: ${widget.note.path}");
_initialContent = "";
}
@ -86,9 +89,18 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
await widget.note.writeAsString(_controller.text);
_initialContent = _controller.text; // Update initial state
print("✅ Note saved successfully");
debugPrint("✅ Note saved successfully");
} catch (e) {
print("❌ Error saving note: ${widget.note.path}");
debugPrint("❌ Error saving note: ${widget.note.path}");
}
}
void _shareNote() {
if (_controller.text.isNotEmpty) {
SharePlus.instance.share(ShareParams(
text: _controller.text,
subject: widget.note.uri.pathSegments.last,
));
}
}
@ -108,7 +120,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
TextButton(
onPressed: () async {
await _saveNote();
Navigator.of(context).pop(true); // Save and exit
if (context.mounted) Navigator.of(context).pop(true);
},
child: Text("Save"),
),
@ -137,8 +149,13 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: _onWillPop,
return PopScope(
canPop: false,
onPopInvokedWithResult: (bool didPop, Object? result) async {
if (didPop) return;
final bool shouldPop = await _onWillPop();
if (shouldPop && context.mounted) Navigator.of(context).pop();
},
child: Scaffold(
appBar: AppBar(
title: Text(widget.note.uri.pathSegments.last.replaceAll('.md', '')),
@ -146,7 +163,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
icon: Icon(Icons.arrow_back),
onPressed: () async {
if (await _onWillPop()) {
Navigator.pop(context);
if (context.mounted) Navigator.pop(context);
}
},
),
@ -157,10 +174,13 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
icon: SvgPicture.asset(
"assets/blaster.svg",
width: 30,
color: Colors.orange,
colorFilter: const ColorFilter.mode(Colors.orange, BlendMode.srcIn),
),
onSelected: (String value) {
switch (value) {
case 'Share': // New case for sharing
_shareNote();
break;
case 'Save':
_saveNote();
break;
@ -175,6 +195,14 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
}
},
itemBuilder: (BuildContext context) => [
PopupMenuItem<String>( // Share button
value: 'Share',
child: ListTile(
leading: Icon(Icons.share_outlined),
title: Text("Share"),
),
),
PopupMenuDivider(),
PopupMenuItem<String>(
value: 'Save',
child: ListTile(
@ -193,6 +221,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
: "Enable Autosave"),
),
),
PopupMenuDivider(),
PopupMenuItem<String>(
enabled: false,
child: Column(
@ -219,6 +248,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
],
),
),
PopupMenuDivider(),
PopupMenuItem<String>(
value: 'Toggle Preview',
child: ListTile(