Skip to content

Commit 1719d61

Browse files
committed
create and use WhitePopupMenuSelectableText in place of SelectableText
1 parent 5f16617 commit 1719d61

File tree

5 files changed

+57
-13
lines changed

5 files changed

+57
-13
lines changed

src/client/gui/lib/extensions.dart

+42
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,45 @@ extension NullableMap<T> on T? {
107107
}
108108
}
109109
}
110+
111+
/// A custom wrapper for SelectableText with a white popup (right-click) menu.
112+
class WhitePopupMenuSelectableText extends StatelessWidget {
113+
final String text;
114+
final TextStyle? style;
115+
final TextAlign? textAlign;
116+
final int? maxLines;
117+
118+
const WhitePopupMenuSelectableText({
119+
super.key,
120+
required this.text,
121+
this.style,
122+
this.textAlign,
123+
this.maxLines,
124+
});
125+
126+
@override
127+
Widget build(BuildContext context) {
128+
final textButtonStyle = Theme.of(context).textButtonTheme.style?.copyWith(
129+
backgroundColor: const WidgetStatePropertyAll(Colors.white),
130+
);
131+
132+
return SelectableText(
133+
text,
134+
style: style?.copyWith(overflow: TextOverflow.ellipsis) ?? const TextStyle(overflow: TextOverflow.ellipsis),
135+
textAlign: textAlign,
136+
maxLines: maxLines,
137+
contextMenuBuilder: (context, editableTextState) {
138+
return TapRegion(
139+
onTapOutside: (_) => ContextMenuController.removeAny(),
140+
child: TextButtonTheme(
141+
data: TextButtonThemeData(style: textButtonStyle),
142+
child: AdaptiveTextSelectionToolbar.buttonItems(
143+
anchors: editableTextState.contextMenuAnchors,
144+
buttonItems: editableTextState.contextMenuButtonItems,
145+
),
146+
),
147+
);
148+
},
149+
);
150+
}
151+
}

src/client/gui/lib/vm_details/ip_addresses.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class IpAddresses extends StatelessWidget {
1717
Expanded(
1818
child: Tooltip(
1919
message: firstIp,
20-
child: SelectableText(firstIp.nonBreaking, maxLines: 1),
20+
child: WhitePopupMenuSelectableText(text: firstIp.nonBreaking, maxLines: 1),
2121
),
2222
),
2323
if (restIps.isNotEmpty)

src/client/gui/lib/vm_details/memory_usage.dart

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import 'package:flutter/material.dart';
22

3+
import '../extensions.dart';
4+
35
class MemoryUsage extends StatelessWidget {
46
final String used;
57
final String total;
@@ -21,8 +23,8 @@ class MemoryUsage extends StatelessWidget {
2123
color: value < 0.8 ? normalColor : almostFullColor,
2224
);
2325

24-
final label = SelectableText(
25-
value != 0 ? '${_formatMemory(used)} / ${_formatMemory(total)}' : '-',
26+
final label = WhitePopupMenuSelectableText(
27+
text: value != 0 ? '${_formatMemory(used)} / ${_formatMemory(total)}' : '-',
2628
style: const TextStyle(fontSize: 11),
2729
);
2830

src/client/gui/lib/vm_details/vm_details_general.dart

+8-8
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ class VmDetailsHeader extends ConsumerWidget {
7676

7777
final list = [
7878
Expanded(
79-
child: SelectableText(
80-
name.nonBreaking,
79+
child: WhitePopupMenuSelectableText(
80+
text: name.nonBreaking,
8181
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w300),
8282
maxLines: 1,
8383
textAlign: TextAlign.start,
@@ -150,29 +150,29 @@ class GeneralDetails extends ConsumerWidget {
150150
width: 150,
151151
height: baseVmStatHeight,
152152
label: 'IMAGE',
153-
child: SelectableText(info.instanceInfo.currentRelease),
153+
child: WhitePopupMenuSelectableText(text: info.instanceInfo.currentRelease),
154154
);
155155

156156
final privateIp = VmStat(
157157
width: 150,
158158
height: baseVmStatHeight,
159159
label: 'PRIVATE IP',
160-
child: SelectableText(info.instanceInfo.ipv4.firstOrNull ?? '-'),
160+
child: WhitePopupMenuSelectableText(text: info.instanceInfo.ipv4.firstOrNull ?? '-'),
161161
);
162162

163163
final publicIp = VmStat(
164164
width: 150,
165165
height: baseVmStatHeight,
166166
label: 'PUBLIC IP',
167-
child: SelectableText(info.instanceInfo.ipv4.skip(1).firstOrNull ?? '-'),
167+
child: WhitePopupMenuSelectableText(text: info.instanceInfo.ipv4.skip(1).firstOrNull ?? '-'),
168168
);
169169

170170
final created = VmStat(
171171
width: 140,
172172
height: baseVmStatHeight,
173173
label: 'CREATED',
174-
child: SelectableText(
175-
DateFormat('yyyy-MM-dd HH:mm:ss')
174+
child: WhitePopupMenuSelectableText(
175+
text: DateFormat('yyyy-MM-dd HH:mm:ss')
176176
.format(info.instanceInfo.creationTimestamp.toDateTime()),
177177
),
178178
);
@@ -181,7 +181,7 @@ class GeneralDetails extends ConsumerWidget {
181181
width: 300,
182182
height: baseVmStatHeight,
183183
label: 'UPTIME',
184-
child: SelectableText(info.instanceInfo.uptime),
184+
child: WhitePopupMenuSelectableText(text: info.instanceInfo.uptime),
185185
);
186186

187187
return Column(

src/client/gui/lib/vm_table/vm_table_headers.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ final headers = <TableHeader<VmInfo>>[
7272
minWidth: 70,
7373
cellBuilder: (info) {
7474
final image = info.instanceInfo.currentRelease;
75-
return SelectableText(
76-
image.isNotBlank ? image.nonBreaking : '-',
75+
return WhitePopupMenuSelectableText(
76+
text: image.isNotBlank ? image.nonBreaking : '-',
7777
maxLines: 1,
7878
);
7979
},

0 commit comments

Comments
 (0)