fluffychat/lib/utils/contextual_actions.dart
TheOneWithTheBraid 49f0a5bde8 feat: add context menu actions for desktops
Related: #849

Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2022-03-02 20:28:16 +01:00

79 lines
2.2 KiB
Dart

import 'package:flutter/material.dart';
class ContextualActions extends InheritedWidget {
final ContextualActionState _state = ContextualActionState();
ContextualActions({Key? key, required Widget child})
: super(key: key, child: child);
static ContextualActions of(BuildContext context) {
final ContextualActions? result =
context.dependOnInheritedWidgetOfExactType<ContextualActions>();
assert(result != null, 'No ContextualActions found in context');
return result!;
}
Set<ContextualAction> get actions => _state.actions;
set actions(Set<ContextualAction> actions) => _state.actions = actions;
List<Widget> buildAppBar() => _state.buildAppBar();
List<Widget> buildContextMenu(BuildContext context) =>
_state.buildContextMenu(context);
@override
bool updateShouldNotify(covariant ContextualActions oldWidget) =>
_state != oldWidget._state;
}
class ContextualActionState {
/// the currently set [ContextualActions]
///
/// use [replace] instead of `=` operator
Set<ContextualAction> actions = {};
Set<ContextualAction> contextMenuOnly = {};
/// unregisters all present actions and adds riven [newActions]
void replace(Iterable<ContextualAction> newActions) {
actions.removeWhere((element) => true);
actions.addAll(newActions);
}
/// buildseach item of [actions] as [IconButton] for use in AppBar
List<Widget> buildAppBar() {
return actions
.map(
(action) => IconButton(
icon: action.icon,
tooltip: action.label,
onPressed: action.action,
),
)
.toList();
}
/// builds each item of [actions] as [ListTile] for use in a [ContextMenuArea]
List<Widget> buildContextMenu(BuildContext context) {
return actions
.map(
(action) => ListTile(
leading: action.icon,
title: Text(action.label),
onTap: () {
Navigator.of(context).pop();
action.action.call();
},
),
)
.toList();
}
}
class ContextualAction {
final VoidCallback action;
final Widget icon;
final String label;
const ContextualAction(
{required this.action, required this.icon, required this.label});
}