Fix up some of the todos
This commit is contained in:
159
lib/main.dart
159
lib/main.dart
@@ -1,8 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
// TODO: Fix "load dependencies", it causes fake errors between expansions and base game
|
||||
// TODO: Add an icon for incompatibilities on the mod list
|
||||
// TODO: Get rid of the demo button WHAT THE FUCK IS THE DEMO BUTTON??
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rimworld_modman/logger.dart';
|
||||
import 'package:rimworld_modman/components/html_tooltip.dart';
|
||||
@@ -31,6 +29,7 @@ class AppThemeExtension extends ThemeExtension<AppThemeExtension> {
|
||||
final Color linkColor;
|
||||
final Color loadAfterColor;
|
||||
final Color loadBeforeColor;
|
||||
final Color incompatibleColor;
|
||||
|
||||
AppThemeExtension({
|
||||
required this.iconSizeSmall,
|
||||
@@ -52,6 +51,7 @@ class AppThemeExtension extends ThemeExtension<AppThemeExtension> {
|
||||
required this.linkColor,
|
||||
required this.loadAfterColor,
|
||||
required this.loadBeforeColor,
|
||||
required this.incompatibleColor,
|
||||
});
|
||||
|
||||
static AppThemeExtension of(BuildContext context) {
|
||||
@@ -79,6 +79,7 @@ class AppThemeExtension extends ThemeExtension<AppThemeExtension> {
|
||||
Color? linkColor,
|
||||
Color? loadAfterColor,
|
||||
Color? loadBeforeColor,
|
||||
Color? incompatibleColor,
|
||||
}) {
|
||||
return AppThemeExtension(
|
||||
iconSizeSmall: iconSizeSmall ?? this.iconSizeSmall,
|
||||
@@ -101,6 +102,7 @@ class AppThemeExtension extends ThemeExtension<AppThemeExtension> {
|
||||
linkColor: linkColor ?? this.linkColor,
|
||||
loadAfterColor: loadAfterColor ?? this.loadAfterColor,
|
||||
loadBeforeColor: loadBeforeColor ?? this.loadBeforeColor,
|
||||
incompatibleColor: incompatibleColor ?? this.incompatibleColor,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -138,6 +140,7 @@ class AppThemeExtension extends ThemeExtension<AppThemeExtension> {
|
||||
linkColor: Color.lerp(linkColor, other.linkColor, t)!,
|
||||
loadAfterColor: Color.lerp(loadAfterColor, other.loadAfterColor, t)!,
|
||||
loadBeforeColor: Color.lerp(loadBeforeColor, other.loadBeforeColor, t)!,
|
||||
incompatibleColor: Color.lerp(incompatibleColor, other.incompatibleColor, t)!,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -167,6 +170,7 @@ class AppThemeExtension extends ThemeExtension<AppThemeExtension> {
|
||||
linkColor: Colors.orange,
|
||||
loadAfterColor: Colors.blue,
|
||||
loadBeforeColor: Colors.green,
|
||||
incompatibleColor: Colors.red.shade400,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -267,10 +271,6 @@ class _ModManagerHomePageState extends State<ModManagerHomePage> {
|
||||
icon: Icon(Icons.build),
|
||||
label: 'Troubleshoot',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.format_paint),
|
||||
label: 'Demo',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -302,6 +302,8 @@ class _ModManagerPageState extends State<ModManagerPage> {
|
||||
|
||||
final TextEditingController _searchController = TextEditingController();
|
||||
String _searchQuery = '';
|
||||
bool _useRegex = false;
|
||||
RegExp? _searchRegex;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -310,12 +312,6 @@ class _ModManagerPageState extends State<ModManagerPage> {
|
||||
if (modManager.mods.isNotEmpty) {
|
||||
_loadModsFromGlobalState();
|
||||
}
|
||||
|
||||
_searchController.addListener(() {
|
||||
setState(() {
|
||||
_searchQuery = _searchController.text.toLowerCase();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -409,27 +405,49 @@ class _ModManagerPageState extends State<ModManagerPage> {
|
||||
|
||||
Widget _buildSplitView() {
|
||||
// Filter both available and active mods based on search query
|
||||
final filteredAvailableMods =
|
||||
_searchQuery.isEmpty
|
||||
? _availableMods
|
||||
: _availableMods
|
||||
.where(
|
||||
(mod) =>
|
||||
mod.name.toLowerCase().contains(_searchQuery) ||
|
||||
mod.id.toLowerCase().contains(_searchQuery),
|
||||
)
|
||||
.toList();
|
||||
List<Mod> filteredAvailableMods;
|
||||
List<Mod> filteredActiveMods;
|
||||
|
||||
final filteredActiveMods =
|
||||
_searchQuery.isEmpty
|
||||
? _activeMods
|
||||
: _activeMods
|
||||
.where(
|
||||
(mod) =>
|
||||
mod.name.toLowerCase().contains(_searchQuery) ||
|
||||
mod.id.toLowerCase().contains(_searchQuery),
|
||||
)
|
||||
.toList();
|
||||
if (_searchQuery.isEmpty) {
|
||||
filteredAvailableMods = _availableMods;
|
||||
filteredActiveMods = _activeMods;
|
||||
} else {
|
||||
if (_useRegex && _searchRegex != null) {
|
||||
// Use regex pattern for filtering
|
||||
filteredAvailableMods = _availableMods
|
||||
.where(
|
||||
(mod) =>
|
||||
_searchRegex!.hasMatch(mod.name.toLowerCase()) ||
|
||||
_searchRegex!.hasMatch(mod.id.toLowerCase()),
|
||||
)
|
||||
.toList();
|
||||
|
||||
filteredActiveMods = _activeMods
|
||||
.where(
|
||||
(mod) =>
|
||||
_searchRegex!.hasMatch(mod.name.toLowerCase()) ||
|
||||
_searchRegex!.hasMatch(mod.id.toLowerCase()),
|
||||
)
|
||||
.toList();
|
||||
} else {
|
||||
// Use simple string contains for filtering
|
||||
filteredAvailableMods = _availableMods
|
||||
.where(
|
||||
(mod) =>
|
||||
mod.name.toLowerCase().contains(_searchQuery) ||
|
||||
mod.id.toLowerCase().contains(_searchQuery),
|
||||
)
|
||||
.toList();
|
||||
|
||||
filteredActiveMods = _activeMods
|
||||
.where(
|
||||
(mod) =>
|
||||
mod.name.toLowerCase().contains(_searchQuery) ||
|
||||
mod.id.toLowerCase().contains(_searchQuery),
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
@@ -457,6 +475,51 @@ class _ModManagerPageState extends State<ModManagerPage> {
|
||||
)
|
||||
: null,
|
||||
),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_searchQuery = value.toLowerCase();
|
||||
|
||||
// Try to compile regex if regex mode is enabled
|
||||
if (_useRegex && _searchQuery.isNotEmpty) {
|
||||
try {
|
||||
_searchRegex = RegExp(_searchQuery, caseSensitive: false);
|
||||
} catch (e) {
|
||||
// If regex is invalid, fallback to normal search
|
||||
_searchRegex = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
// Regex toggle
|
||||
Tooltip(
|
||||
message: 'Use regex pattern matching',
|
||||
child: Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
value: _useRegex,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_useRegex = value ?? false;
|
||||
|
||||
// Try to compile regex if toggled on
|
||||
if (_useRegex && _searchQuery.isNotEmpty) {
|
||||
try {
|
||||
_searchRegex = RegExp(_searchQuery, caseSensitive: false);
|
||||
} catch (e) {
|
||||
// If regex fails, keep checkbox on but disable regex internally
|
||||
_searchRegex = null;
|
||||
}
|
||||
} else {
|
||||
_searchRegex = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
const Text('Regex'),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -841,6 +904,22 @@ class _ModManagerPageState extends State<ModManagerPage> {
|
||||
).iconSizeRegular,
|
||||
),
|
||||
),
|
||||
if (mod.incompatibilities.isNotEmpty)
|
||||
Tooltip(
|
||||
message:
|
||||
'Incompatible with:\n${mod.incompatibilities.join('\n')}',
|
||||
child: Icon(
|
||||
Icons.warning_amber_rounded,
|
||||
color:
|
||||
AppThemeExtension.of(
|
||||
context,
|
||||
).incompatibleColor,
|
||||
size:
|
||||
AppThemeExtension.of(
|
||||
context,
|
||||
).iconSizeRegular,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
@@ -1097,6 +1176,22 @@ class _ModManagerPageState extends State<ModManagerPage> {
|
||||
).iconSizeRegular,
|
||||
),
|
||||
),
|
||||
if (mod.incompatibilities.isNotEmpty)
|
||||
Tooltip(
|
||||
message:
|
||||
'Incompatible with:\n${mod.incompatibilities.join('\n')}',
|
||||
child: Icon(
|
||||
Icons.warning_amber_rounded,
|
||||
color:
|
||||
AppThemeExtension.of(
|
||||
context,
|
||||
).incompatibleColor,
|
||||
size:
|
||||
AppThemeExtension.of(
|
||||
context,
|
||||
).iconSizeRegular,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
|
Reference in New Issue
Block a user