Files
999/lib/main.dart
T
Alma Alexyz fbf04d90db feat: embed a Flutter G4F client with Cronet, cookie jar, and origin WebView
Port the Oracle off the Python g4f container onto on-device providers: Chromium HTTP via Cronet, a shared cookie session, IterList retry, hosted OpenAI-compat aggregators, and same-origin WebView fallbacks instead of CORS fetch.
2026-09-01 22:05:38 +05:00

269 lines
8.7 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'screens/history_screen.dart';
import 'screens/home_search_screen.dart';
import 'screens/oracle_chat_screen.dart';
import 'screens/provider_bakeoff_screen.dart';
import 'services/words_repository.dart';
import 'widgets/gradient_star_badge.dart';
import 'g4f/client.dart';
import 'g4f/models.dart';
import 'g4f/providers/chatgpt_oss.dart';
import 'g4f/providers/pollinations.dart';
import 'g4f/providers/teach_anything.dart';
import 'g4f/providers/yqcloud.dart';
import 'g4f/providers/deep_ai.dart';
import 'g4f/providers/phind_ai.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await WordsRepository().init();
runApp(const Words999App());
}
class Words999App extends StatefulWidget {
const Words999App({super.key});
@override
State<Words999App> createState() => _Words999AppState();
}
class _Words999AppState extends State<Words999App> {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Оракул 999 Символов',
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.dark, // Default to rich mystical dark mode
darkTheme: ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
scaffoldBackgroundColor: const Color(0xFF0C0E1A),
colorScheme: const ColorScheme.dark(
primary: Color(0xFFFFD54F), // Celestial Yellow Gold
onPrimary: Color(0xFF1B1D30),
primaryContainer: Color(0xFF2A2D4A),
onPrimaryContainer: Color(0xFFFFF9C4),
secondary: Color(0xFF80DEEA),
surface: Color(0xFF151829),
onSurface: Color(0xFFE8EAF6),
surfaceContainerHigh: Color(0xFF1E2238),
surfaceContainerHighest: Color(0xFF262B44),
outline: Color(0xFF9FA8DA),
outlineVariant: Color(0xFF3949AB),
),
fontFamily: 'Roboto',
appBarTheme: const AppBarTheme(
backgroundColor: Color(0xFF0C0E1A),
elevation: 0,
scrolledUnderElevation: 3,
centerTitle: false,
titleTextStyle: TextStyle(
color: Color(0xFFFFF9C4),
fontSize: 20,
fontWeight: FontWeight.w900,
letterSpacing: 0.5,
),
),
navigationBarTheme: NavigationBarThemeData(
backgroundColor: const Color(0xFF101222),
indicatorColor: const Color(0xFF2A2D4A),
labelTextStyle: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
return const TextStyle(
color: Color(0xFFFFF9C4),
fontWeight: FontWeight.bold,
fontSize: 12,
);
}
return const TextStyle(
color: Color(0xFF8C93B8),
fontSize: 12,
);
}),
),
),
home: const bool.fromEnvironment('ORACLE_BAKEOFF')
? const ProviderBakeoffScreen()
: const MainNavigationContainer(),
);
}
}
class MainNavigationContainer extends StatefulWidget {
const MainNavigationContainer({super.key});
@override
State<MainNavigationContainer> createState() => _MainNavigationContainerState();
}
class _MainNavigationContainerState extends State<MainNavigationContainer> {
int _currentIndex = 0;
final List<Widget> _screens = const [
HomeSearchScreen(),
HistoryScreen(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _currentIndex,
children: _screens,
),
bottomNavigationBar: NavigationBar(
selectedIndex: _currentIndex,
onDestinationSelected: (index) {
setState(() => _currentIndex = index);
HapticFeedback.selectionClick();
},
destinations: const [
NavigationDestination(
icon: Icon(Icons.casino_outlined),
selectedIcon: GradientStar(size: 22),
label: 'Оракул',
),
NavigationDestination(
icon: Icon(Icons.history_rounded),
selectedIcon: GradientStar(size: 22),
label: 'История',
),
],
),
floatingActionButton: GestureDetector(
onLongPress: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const ProviderBakeoffScreen()),
);
},
child: FloatingActionButton.extended(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const OracleChatScreen()),
);
},
icon: const Icon(Icons.auto_awesome),
label: const Text("ОРАКУЛ"),
),
),
);
}
}
class _G4FTestHelper {
Future<String> testAI() async {
final client = G4FClient();
// We access the providers from the client's internal list by just creating them here to test directly.
// Or simply test the main client logic. To test all, we will test them individually.
// We import them dynamically inside the test to keep main.dart clean long-term
final results = <String>[];
final messages = [Message(role: Role.user, content: "Коротко ответь 'Работает' и добавь одно случайное эмодзи.")];
// Yqcloud
try {
print("⏳ Тестируем Yqcloud...");
results.add("📡 Yqcloud: " + await _testProvider(client, "Yqcloud", messages));
print("✅ Yqcloud ответил!");
} catch (e) {
print("❌ Yqcloud Ошибка: $e");
results.add("❌ Yqcloud Ошибка: $e");
}
// TeachAnything
try {
print("⏳ Тестируем TeachAnything...");
results.add("📡 TeachAnything: " + await _testProvider(client, "TeachAnything", messages));
print("✅ TeachAnything ответил!");
} catch (e) {
print("❌ TeachAnything Ошибка: $e");
results.add("❌ TeachAnything Ошибка: $e");
}
// ChatGptOss
try {
print("⏳ Тестируем ChatGptOss...");
results.add("📡 ChatGptOss: " + await _testProvider(client, "ChatGptOss", messages));
print("✅ ChatGptOss ответил!");
} catch (e) {
print("❌ ChatGptOss Ошибка: $e");
results.add("❌ ChatGptOss Ошибка: $e");
}
// Pollinations
try {
print("⏳ Тестируем Pollinations...");
results.add("📡 Pollinations: " + await _testProvider(client, "Pollinations", messages));
print("✅ Pollinations ответил!");
} catch (e) {
print("❌ Pollinations Ошибка: $e");
results.add("❌ Pollinations Ошибка: $e");
}
// DeepAi
try {
print("⏳ Тестируем DeepAi...");
results.add("📡 DeepAi: " + await _testProvider(client, "DeepAi", messages));
print("✅ DeepAi ответил!");
} catch (e) {
print("❌ DeepAi Ошибка: $e");
results.add("❌ DeepAi Ошибка: $e");
}
// PhindAi
try {
print("⏳ Тестируем PhindAi...");
results.add("📡 PhindAi: " + await _testProvider(client, "PhindAi", messages));
print("✅ PhindAi ответил!");
} catch (e) {
print("❌ PhindAi Ошибка: $e");
results.add("❌ PhindAi Ошибка: $e");
}
// DeepInfraWebView
try {
print("⏳ Тестируем DeepInfraWebView (в скрытом браузере)...");
String finalResult = "";
await for (final chunk in client.chat.completions.createStream(messages: messages)) {
finalResult += chunk;
}
results.add("📡 DeepInfraWebView: $finalResult");
print("✅ DeepInfraWebView ответил!");
} catch (e) {
print("❌ DeepInfraWebView Ошибка: $e");
results.add("❌ DeepInfraWebView Ошибка: $e");
}
print("🎉 Все тесты завершены!");
return results.join("\\n\\n");
}
Future<String> _testProvider(G4FClient client, String providerName, List<Message> messages) async {
try {
dynamic provider;
switch (providerName) {
case "Yqcloud": provider = Yqcloud(); break;
case "TeachAnything": provider = TeachAnything(); break;
case "ChatGptOss": provider = ChatGptOss(); break;
case "Pollinations": provider = Pollinations(); break;
case "DeepAi": provider = DeepAi(); break;
case "PhindAi": provider = PhindAi(); break;
}
final stream = provider.createAsyncGenerator(
provider.defaultModel,
messages,
stream: false,
);
return await stream.join();
} catch (e) {
return "ОШИБКА: $e";
}
}
}