1
0
Dieser Commit ist enthalten in:
Chaoscaot 2023-04-14 18:53:34 +02:00
Ursprung c95fda17ca
Commit 89d1e1d5b5
4 geänderte Dateien mit 341 neuen und 82 gelöschten Zeilen

Datei anzeigen

@ -27,6 +27,8 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:steamwar_multitool/src/provider/provider.dart';
import 'package:steamwar_multitool/src/screens/home/lists/events_list.dart';
import 'lists/mod_list.dart';
class HomeScreen extends HookConsumerWidget {
const HomeScreen({Key? key}) : super(key: key);
@ -79,7 +81,6 @@ class HomeScreen extends HookConsumerWidget {
label: Text("Mods"),
selectedIcon: Icon(Icons.developer_mode),
),
const Spacer(),
const NavigationDrawerDestination(
icon: Icon(Icons.settings_outlined),
label: Text("Settings"),
@ -129,17 +130,12 @@ class HomeScreen extends HookConsumerWidget {
),
],
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: IndexedStack(
index: navRailIndex.value,
children: const [
//ServerListComponent(),
EventListComponent(),
Placeholder(),
//ModListComponent(),
],
),
body: IndexedStack(
index: navRailIndex.value,
children: const [
EventListComponent(),
ModListComponent(),
],
),
);
}

Datei anzeigen

@ -38,53 +38,56 @@ class EventListComponent extends HookConsumerWidget {
final pastEvents =
data.where((element) => !element.isUpcoming && !element.isCurrent);
final currentEvent = data.indexWhere((element) => element.isCurrent);
return ListView(
children: [
Row(
children: [
FilledButton.icon(
onPressed: () {
showModalBottomSheet(
constraints: BoxConstraints(maxWidth: 500),
context: context,
builder: (context) => const CreateEventDialog());
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: ListView(
children: [
Row(
children: [
FilledButton.icon(
onPressed: () {
showModalBottomSheet(
constraints: BoxConstraints(maxWidth: 500),
context: context,
builder: (context) => const CreateEventDialog());
},
label: const Text("Create Event"),
icon: const Icon(Icons.add),
),
],
),
const SizedBox(
height: 16,
),
if (currentEvent != -1)
ListTile(
title: Text(
data[currentEvent].name,
),
subtitle: const Text(
"Current Event",
),
leading: const Icon(Icons.priority_high),
onTap: () {
context.go("/event/${data[currentEvent].id}");
},
label: const Text("Create Event"),
icon: const Icon(Icons.add),
),
],
),
const SizedBox(
height: 16,
),
if (currentEvent != -1)
ListTile(
title: Text(
data[currentEvent].name,
if (upcomingEvents.isNotEmpty)
Text(
"Upcoming Events",
style: Theme.of(context).textTheme.headlineSmall,
),
subtitle: const Text(
"Current Event",
...upcomingEvents.map(
(e) => EventTile(e),
),
if (pastEvents.isNotEmpty)
Text(
"Past Events",
style: Theme.of(context).textTheme.headlineSmall,
),
leading: const Icon(Icons.priority_high),
onTap: () {
context.go("/event/${data[currentEvent].id}");
},
),
if (upcomingEvents.isNotEmpty)
Text(
"Upcoming Events",
style: Theme.of(context).textTheme.headlineSmall,
),
...upcomingEvents.map(
(e) => EventTile(e),
),
if (pastEvents.isNotEmpty)
Text(
"Past Events",
style: Theme.of(context).textTheme.headlineSmall,
),
...pastEvents.map((e) => EventTile(e)),
],
...pastEvents.map((e) => EventTile(e)),
],
),
);
}, error: (err, stack) {
return ErrorComponent(err, stack);

Datei anzeigen

@ -18,36 +18,296 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:steamwar_multitool/src/components/error.dart';
import 'package:steamwar_multitool/src/provider/mods.dart';
import 'package:steamwar_multitool/src/types/mods.dart';
import 'package:url_launcher/link.dart';
class ModListComponent extends HookConsumerWidget {
const ModListComponent({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final list = ref.watch(uncheckedMods);
final tabController = useTabController(initialLength: 2);
return list.when(
return Column(
children: [
TabBar(
tabs: [
const Tab(
text: "Unrated",
),
Tab(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(Icons.search),
Text("Search"),
],
),
)
],
controller: tabController,
),
Expanded(
child: TabBarView(
controller: tabController,
children: const [
UnratedModsList(),
SearchModsList(),
],
),
),
],
);
}
}
class UnratedModsList extends HookConsumerWidget {
const UnratedModsList({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final mods = ref.watch(uncheckedMods);
var i = 0;
return mods.when(
data: (data) {
return ListView(
shrinkWrap: true,
children: [
Center(
child: Text("WIP",
style: Theme.of(context).textTheme.headline5)),
...data
.map(
(e) => ListTile(
title: Text(e.name),
subtitle: Text(e.platform.name),
for (final mod in data)
ExpansionTile(
title: Text(mod.name),
subtitle:
Text("Modloader: ${mod.platform.name.capitalize()}"),
initiallyExpanded: i++ == 0,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Link(
target: LinkTarget.blank,
uri: Uri.tryParse(
"https://modrinth.com/mods?q=${mod.name}"),
builder: (context, followLink) {
return FilledButton.tonalIcon(
onPressed: followLink,
label: const Text("Modrinth"),
icon: const Icon(Icons.open_in_new),
);
}),
Link(
target: LinkTarget.blank,
uri: Uri.tryParse(
"https://beta.curseforge.com/minecraft/search?search=${mod.name}"),
builder: (context, followLink) {
return FilledButton.tonalIcon(
onPressed: followLink,
label: const Text("Curseforge"),
icon: const Icon(Icons.open_in_new),
);
}),
Link(
target: LinkTarget.blank,
uri: Uri.tryParse(
"https://github.com/search?q=${mod.name}"),
builder: (context, followLink) {
return FilledButton.tonalIcon(
onPressed: followLink,
label: const Text("Github"),
icon: const Icon(Icons.open_in_new),
);
}),
],
),
)
.toList()
const Divider(),
SegmentedButton(
segments: [
for (final type in ModType.values)
ButtonSegment(
value: type,
label: Text(type.name.capitalize()),
)
],
selected: {mod.type},
multiSelectionEnabled: false,
emptySelectionAllowed: false,
onSelectionChanged: (value) async {
final repo = await ref.read(modRepository.future);
await repo.updateMod(
mod.platform, mod.name, value.first);
ref.invalidate(uncheckedMods);
},
),
const SizedBox(height: 10),
],
),
],
);
},
error: (err, stack) => ErrorComponent(err, stack),
loading: () => const Center(child: CircularProgressIndicator()));
loading: () => const LinearProgressIndicator());
}
}
class SearchModsList extends HookConsumerWidget {
const SearchModsList({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final modsList = ref.watch(mods);
final nameFilter = useState("");
final platformFilter = useState(Platform.values.toSet());
final typeFilter = useState(ModType.values.toSet());
return ListView(
shrinkWrap: true,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
TextField(
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: "Name",
),
onChanged: (value) {
nameFilter.value = value;
},
),
const SizedBox(height: 10),
SegmentedButton(
segments: [
for (final platform in Platform.values)
ButtonSegment(
value: platform,
label: Text(platform.name.capitalize()),
)
],
selected: platformFilter.value,
multiSelectionEnabled: true,
emptySelectionAllowed: false,
onSelectionChanged: (value) {
platformFilter.value = value;
},
),
const SizedBox(height: 10),
SegmentedButton(
segments: [
for (final type in ModType.values)
ButtonSegment(
value: type,
label: Text(type.name.capitalize()),
)
],
selected: typeFilter.value,
multiSelectionEnabled: true,
emptySelectionAllowed: false,
onSelectionChanged: (value) {
typeFilter.value = value;
},
),
],
),
),
const Divider(),
...modsList.when(
data: (data) {
final filtered = data
.where((mod) =>
(nameFilter.value.isEmpty ||
mod.name
.toLowerCase()
.contains(nameFilter.value.toLowerCase())) &&
platformFilter.value.contains(mod.platform) &&
typeFilter.value.contains(mod.type))
.toList();
return filtered.map((mod) {
return ExpansionTile(
title: Text(mod.name),
subtitle:
Text("Modloader: ${mod.platform.name.capitalize()}"),
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Link(
target: LinkTarget.blank,
uri: Uri.tryParse(
"https://modrinth.com/mods?q=${mod.name}"),
builder: (context, followLink) {
return FilledButton.tonalIcon(
onPressed: followLink,
label: const Text("Modrinth"),
icon: const Icon(Icons.open_in_new),
);
}),
Link(
target: LinkTarget.blank,
uri: Uri.tryParse(
"https://beta.curseforge.com/minecraft/search?search=${mod.name}"),
builder: (context, followLink) {
return FilledButton.tonalIcon(
onPressed: followLink,
label: const Text("Curseforge"),
icon: const Icon(Icons.open_in_new),
);
}),
Link(
target: LinkTarget.blank,
uri: Uri.tryParse(
"https://github.com/search?q=${mod.name}"),
builder: (context, followLink) {
return FilledButton.tonalIcon(
onPressed: followLink,
label: const Text("Github"),
icon: const Icon(Icons.open_in_new),
);
}),
],
),
const Divider(),
SegmentedButton(
segments: [
for (final type in ModType.values)
ButtonSegment(
value: type,
label: Text(type.name.capitalize()),
)
],
selected: {mod.type},
multiSelectionEnabled: false,
emptySelectionAllowed: false,
onSelectionChanged: (value) async {
final repo = await ref.read(modRepository.future);
await repo.updateMod(
mod.platform, mod.name, value.first);
ref.invalidate(mods);
},
),
const SizedBox(height: 10),
],
);
});
},
error: (err, stack) => [ErrorComponent(err, stack)],
loading: () => const [LinearProgressIndicator()])
],
);
}
}
extension StringExtension on String {
String capitalize() {
return "${this[0].toUpperCase()}${substring(1).toLowerCase()}";
}
}

Datei anzeigen

@ -292,10 +292,10 @@ packages:
dependency: "direct main"
description:
name: go_router
sha256: feab99a20fd248c658c923ba98f4449ca6e575c3dee9fdf07146f4f33482c6bc
sha256: "50bc08b72ede07daaf897deb4c00ca8fd8976c8821a4c84d7aeef0e92d1c5620"
url: "https://pub.dev"
source: hosted
version: "6.5.5"
version: "6.5.6"
graphs:
dependency: transitive
description:
@ -540,10 +540,10 @@ packages:
dependency: transitive
description:
name: shared_preferences_foundation
sha256: cf2a42fb20148502022861f71698db12d937c7459345a1bdaa88fc91a91b3603
sha256: "0c1c16c56c9708aa9c361541a6f0e5cc6fc12a3232d866a687a7b7db30032b07"
url: "https://pub.dev"
source: hosted
version: "2.2.0"
version: "2.2.1"
shared_preferences_linux:
dependency: transitive
description:
@ -705,18 +705,18 @@ packages:
dependency: transitive
description:
name: url_launcher_android
sha256: dd729390aa936bf1bdf5cd1bc7468ff340263f80a2c4f569416507667de8e3c8
sha256: a52628068d282d01a07cd86e6ba99e497aa45ce8c91159015b2416907d78e411
url: "https://pub.dev"
source: hosted
version: "6.0.26"
version: "6.0.27"
url_launcher_ios:
dependency: transitive
description:
name: url_launcher_ios
sha256: "3dedc66ca3c0bef9e6a93c0999aee102556a450afcc1b7bcfeace7a424927d92"
sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2"
url: "https://pub.dev"
source: hosted
version: "6.1.3"
version: "6.1.4"
url_launcher_linux:
dependency: transitive
description:
@ -729,10 +729,10 @@ packages:
dependency: transitive
description:
name: url_launcher_macos
sha256: "0ef2b4f97942a16523e51256b799e9aa1843da6c60c55eefbfa9dbc2dcb8331a"
sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e"
url: "https://pub.dev"
source: hosted
version: "3.0.4"
version: "3.0.5"
url_launcher_platform_interface:
dependency: transitive
description:
@ -777,18 +777,18 @@ packages:
dependency: transitive
description:
name: web_socket_channel
sha256: ca49c0bc209c687b887f30527fb6a9d80040b072cc2990f34b9bec3e7663101b
sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b
url: "https://pub.dev"
source: hosted
version: "2.3.0"
version: "2.4.0"
win32:
dependency: transitive
description:
name: win32
sha256: c9ebe7ee4ab0c2194e65d3a07d8c54c5d00bb001b76081c4a04cdb8448b59e46
sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
url: "https://pub.dev"
source: hosted
version: "3.1.3"
version: "3.1.4"
xdg_directories:
dependency: transitive
description: