prem / lib /keyboard /keyboard_layout.dart
Nitishkumar-ai's picture
Deploy source code to Hugging Face without binaries
c25dcd7
import 'package:flutter/material.dart';
import 'package:virtual_keyboard_multi_language/virtual_keyboard_multi_language.dart';
import 'package:google_fonts/google_fonts.dart';
import '../services/grammar_service.dart';
import '../services/llm_service.dart';
import '../services/storage_service.dart';
import '../kavacha/threat_pack/outgoing_data_shield.dart';
import 'hinglish_ngram.dart';
import 'keyboard_channel.dart';
import 'shortcut_bar.dart';
class PremithiusKeyboard extends StatefulWidget {
const PremithiusKeyboard({Key? key}) : super(key: key);
@override
_PremithiusKeyboardState createState() => _PremithiusKeyboardState();
}
class _PremithiusKeyboardState extends State<PremithiusKeyboard> {
bool _isGenerating = false;
final _grammarService = GrammarService();
final _llmService = LlmService();
final _storageService = StorageService();
final _outgoingShield = OutgoingDataShield();
final _hinglish = HinglishNgram();
@override
void initState() {
super.initState();
_grammarService.init();
}
Future<void> _onShortcutAction(String action) async {
setState(() => _isGenerating = true);
// Fetch current text from IME
String originalText = await KeyboardChannel.getText();
String newText = originalText;
if (action == 'Fix') {
newText = await _grammarService.fixGrammar(originalText);
} else {
newText = await _llmService.processAction(originalText, action);
}
await KeyboardChannel.replaceText(newText);
// Log asynchronously
try {
await _storageService.insertKeyboardLog({
'app_context': 'premithus_ime', // Default context
'original_text': originalText,
'action': action,
'result_text': newText,
'accepted': 1,
'created_at': DateTime.now().millisecondsSinceEpoch,
});
} catch (e) {
debugPrint('Error inserting keyboard log: \$e');
}
if (mounted) {
setState(() => _isGenerating = false);
}
}
void _onKeyPress(VirtualKeyboardKey key) async {
if (key.keyType == VirtualKeyboardKeyType.String) {
KeyboardChannel.commitText(key.text ?? '');
} else if (key.keyType == VirtualKeyboardKeyType.Action) {
switch (key.action) {
case VirtualKeyboardKeyAction.Backspace:
KeyboardChannel.deleteBackward();
break;
case VirtualKeyboardKeyAction.Space:
case VirtualKeyboardKeyAction.Return:
// Check for data leaks on word boundaries
String fullText = await KeyboardChannel.getText();
final shieldResult = _outgoingShield.check(fullText);
if (!shieldResult.isSafe) {
// In a real app we would show a confirmation dialog or red overlay
debugPrint("SHIELD WARNING: \${shieldResult.warningTitle}");
// Simulate temporary block
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(shieldResult.warningMessage ?? "Blocked"), backgroundColor: Colors.red),
);
} else {
KeyboardChannel.commitText(key.action == VirtualKeyboardKeyAction.Space ? ' ' : '\n');
}
break;
default:
break;
}
}
}
@override
Widget build(BuildContext context) {
return Material(
color: Colors.black,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
decoration: BoxDecoration(
color: Colors.black54,
border: Border(bottom: BorderSide(color: Colors.white.withValues(alpha: 0.05))),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
const Icon(Icons.shield_rounded, color: Colors.blueAccent, size: 14),
const SizedBox(width: 6),
Text(
"KAVACHA PROTECTED",
style: GoogleFonts.outfit(
color: Colors.blueAccent,
fontSize: 10,
fontWeight: FontWeight.w800,
letterSpacing: 1.1,
),
),
],
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2),
decoration: BoxDecoration(
color: Colors.greenAccent.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(4),
),
child: Text(
"SAFE",
style: GoogleFonts.outfit(
color: Colors.greenAccent,
fontSize: 10,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
ShortcutBar(
onAction: _onShortcutAction,
isGenerating: _isGenerating,
),
Container(
color: Colors.black,
child: VirtualKeyboard(
height: 250,
textColor: Colors.white,
type: VirtualKeyboardType.Alphanumeric,
textController: TextEditingController(),
postKeyPress: _onKeyPress,
),
),
],
),
);
}
}