8fffafde47
Translations are provided in *.arb* format. Some keys have descriptions (indicated by leading @-symbol). Descriptions should not be copied into the translation itself. Currently only English is supported (app_en.arb), but German is planned. Apparently weblate merged .arb support at some time, so it would be nice to enable community translations at some point.
168 lines
5.1 KiB
Dart
168 lines
5.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
import 'package:outbag_app/backend/permissions.dart';
|
|
import 'package:outbag_app/backend/request.dart';
|
|
import 'package:outbag_app/backend/user.dart';
|
|
import 'package:outbag_app/tools/fetch_wrapper.dart';
|
|
import 'package:provider/provider.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
import '../backend/room.dart';
|
|
|
|
class HomePage extends StatefulWidget {
|
|
const HomePage({super.key});
|
|
@override
|
|
State<HomePage> createState() => _HomePageState();
|
|
}
|
|
|
|
class _HomePageState extends State<HomePage> {
|
|
List<Room> rooms = [];
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
// wait for background room changes
|
|
Room.listen((_) async {
|
|
try {
|
|
final newRooms = await Room.listRooms();
|
|
setState(() {
|
|
rooms = newRooms;
|
|
});
|
|
} catch (_) {}
|
|
});
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) => fetchList());
|
|
}
|
|
|
|
void fetchList() async {
|
|
final sm = ScaffoldMessenger.of(context);
|
|
final user = context.read<User>();
|
|
|
|
// load cached rooms
|
|
try {
|
|
final newRooms = await Room.listRooms();
|
|
setState(() {
|
|
rooms = newRooms;
|
|
});
|
|
} catch (_) {}
|
|
|
|
doNetworkRequest(
|
|
sm,
|
|
req: () => postWithCreadentials(
|
|
path: 'listRooms', credentials: user, target: user.server, body: {}),
|
|
onOK: (body) async {
|
|
final List<Room> list = body['data'].map<Room>((json) {
|
|
return Room.fromJSON(json);
|
|
}).toList();
|
|
for (Room r in list) {
|
|
await r.toDisk();
|
|
}
|
|
},
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text("Outbag"),
|
|
actions: [
|
|
IconButton(
|
|
icon: const Icon(Icons.search),
|
|
tooltip: AppLocalizations.of(context)!.search,
|
|
onPressed: () {
|
|
// show searchbar
|
|
// NOTE: location currently unknown
|
|
},
|
|
),
|
|
MenuAnchor(
|
|
builder: (ctx, controller, child) {
|
|
return IconButton(
|
|
onPressed: () {
|
|
if (controller.isOpen) {
|
|
controller.close();
|
|
} else {
|
|
controller.open();
|
|
}
|
|
},
|
|
icon: const Icon(Icons.more_vert),
|
|
);
|
|
},
|
|
menuChildren: [
|
|
MenuItemButton(
|
|
leadingIcon: const Icon(Icons.settings),
|
|
child: Text(AppLocalizations.of(context)!.settings),
|
|
onPressed: () {
|
|
// show settings screen
|
|
context.goNamed('settings');
|
|
}),
|
|
...(context.watch<AccountMeta?>() != null &&
|
|
(context.watch<AccountMeta?>()?.permissions)! &
|
|
ServerPermission.allManagement !=
|
|
0)
|
|
? [
|
|
MenuItemButton(
|
|
leadingIcon: const Icon(Icons.dns),
|
|
child: Text(AppLocalizations.of(context)!.serverDashboard),
|
|
onPressed: () {
|
|
// show settings screen
|
|
context.goNamed('dash');
|
|
}),
|
|
]
|
|
: [],
|
|
MenuItemButton(
|
|
leadingIcon: const Icon(Icons.info_rounded),
|
|
child: Text(AppLocalizations.of(context)!.about),
|
|
onPressed: () {
|
|
// show about screen
|
|
context.goNamed('about');
|
|
}),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
body: ListView.builder(
|
|
itemCount: rooms.length,
|
|
itemBuilder: (ctx, i) {
|
|
final room = rooms[i];
|
|
return Card(
|
|
margin: const EdgeInsets.all(8.0),
|
|
clipBehavior: Clip.antiAliasWithSaveLayer,
|
|
semanticContainer: true,
|
|
child: InkWell(
|
|
onTap: () {
|
|
// open room
|
|
context.goNamed('room',
|
|
params: {'server': room.serverTag, 'id': room.id});
|
|
},
|
|
onLongPress: () {
|
|
// open bottom sheet
|
|
// NOTE: feature yet to be confirmed
|
|
},
|
|
child: Container(
|
|
padding: const EdgeInsets.fromLTRB(10, 5, 5, 10),
|
|
child: ListTile(
|
|
title: Text(room.name),
|
|
visualDensity: const VisualDensity(vertical: 3),
|
|
subtitle: Text(room.description),
|
|
leading: AspectRatio(
|
|
aspectRatio: 1 / 1,
|
|
child: SvgPicture.asset("${room.icon?.img}"),
|
|
),
|
|
hoverColor: Colors.transparent,
|
|
))));
|
|
},
|
|
),
|
|
floatingActionButton: FloatingActionButton.extended(
|
|
label: Text(AppLocalizations.of(context)!.addRoom),
|
|
icon: const Icon(Icons.add),
|
|
onPressed: () {
|
|
// create new room
|
|
context.goNamed('add-room');
|
|
},
|
|
tooltip: AppLocalizations.of(context)!.addRoomHint,
|
|
),
|
|
);
|
|
}
|
|
}
|