mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-06-02 20:42:12 +00:00
Improved: UI components adapt to native styling
This commit is contained in:
parent
9beb8ef9d7
commit
9e28bb82a2
42 changed files with 62 additions and 61 deletions
|
|
@ -3,7 +3,8 @@
|
|||
## 0.2.25
|
||||
|
||||
- New: Import images from the gallery
|
||||
- Improves: Media files are now stored in the "twonly" album
|
||||
- Improved: Media files are now stored in the dedicated "twonly" album
|
||||
- Improved: UI components adapt to native styling (iOS/Android)
|
||||
- Fix: Migration issue that resulted in a corrupted backup mechanism
|
||||
- Fix: Database issues causing messages to be lost or the database to be corrupted
|
||||
- Fix: Permission view did not disappear after they were granted
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ class _VideoPlayerFileHelperState extends State<VideoPlayerFileHelper> {
|
|||
aspectRatio: _controller.value.aspectRatio,
|
||||
child: VideoPlayerHelper(controller: _controller),
|
||||
)
|
||||
: const CircularProgressIndicator(),
|
||||
: const CircularProgressIndicator.adaptive(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ class _StartNewChatView extends State<AddNewShortcutView> {
|
|||
group: group,
|
||||
fontSize: 15,
|
||||
),
|
||||
trailing: Checkbox(
|
||||
trailing: Checkbox.adaptive(
|
||||
value: _selectedGroups.contains(group.groupId),
|
||||
side: WidgetStateBorderSide.resolveWith(
|
||||
(states) {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class CameraScannedOverlay extends StatelessWidget {
|
|||
const SizedBox(
|
||||
width: 12,
|
||||
height: 12,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
|
||||
)
|
||||
else
|
||||
ColoredBox(
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ class SaveToGalleryButtonState extends State<SaveToGalleryButton> {
|
|||
const SizedBox(
|
||||
width: 12,
|
||||
height: 12,
|
||||
child: CircularProgressIndicator(strokeWidth: 1),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 1),
|
||||
)
|
||||
else
|
||||
_imageSaved
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ class _ShareImageView extends State<ShareImageView> {
|
|||
),
|
||||
Transform.scale(
|
||||
scale: 0.75,
|
||||
child: Checkbox(
|
||||
child: Checkbox.adaptive(
|
||||
value: !hideArchivedUsers,
|
||||
side: WidgetStateBorderSide.resolveWith(
|
||||
(states) {
|
||||
|
|
@ -293,9 +293,9 @@ class _ShareImageView extends State<ShareImageView> {
|
|||
? SizedBox(
|
||||
height: 12,
|
||||
width: 12,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
color: Theme.of(context).colorScheme.inversePrimary,
|
||||
valueColor: AlwaysStoppedAnimation(Theme.of(context).colorScheme.inversePrimary),
|
||||
),
|
||||
)
|
||||
: const FaIcon(FontAwesomeIcons.solidPaperPlane),
|
||||
|
|
@ -382,7 +382,7 @@ class UserList extends StatelessWidget {
|
|||
group: group,
|
||||
fontSize: 15,
|
||||
),
|
||||
trailing: Checkbox(
|
||||
trailing: Checkbox.adaptive(
|
||||
value: selectedGroupIds.contains(group.groupId),
|
||||
side: WidgetStateBorderSide.resolveWith(
|
||||
(states) {
|
||||
|
|
|
|||
|
|
@ -165,7 +165,7 @@ class UserCheckbox extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
Expanded(child: Container()),
|
||||
Checkbox(
|
||||
Checkbox.adaptive(
|
||||
value: isChecked,
|
||||
side: WidgetStateBorderSide.resolveWith(
|
||||
(states) {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class _SelectShowTimeState extends State<SelectShowTime> {
|
|||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Checkbox(
|
||||
Checkbox.adaptive(
|
||||
value: _storeAsDefault,
|
||||
onChanged: (value) => setState(() {
|
||||
_storeAsDefault = !_storeAsDefault;
|
||||
|
|
|
|||
|
|
@ -717,11 +717,9 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
? SizedBox(
|
||||
height: 12,
|
||||
width: 12,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.inversePrimary,
|
||||
valueColor: AlwaysStoppedAnimation(Theme.of(context).colorScheme.inversePrimary),
|
||||
),
|
||||
)
|
||||
: const FaIcon(FontAwesomeIcons.solidPaperPlane),
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ class _DrawLayerState extends State<DrawLayer> {
|
|||
Positioned.fill(
|
||||
child: RotatedBox(
|
||||
quarterTurns: 1,
|
||||
child: Slider(
|
||||
child: Slider.adaptive(
|
||||
value: _sliderValue,
|
||||
thumbColor: currentColor,
|
||||
activeColor: Colors.transparent,
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ class TwitterPostCard extends StatelessWidget {
|
|||
height: 150,
|
||||
color: const Color(0xFFF5F8FA),
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation(twitterBlue),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ class _ChatAskAFriendEntryState extends State<ChatAskAFriendEntry> {
|
|||
child: SizedBox(
|
||||
width: 14,
|
||||
height: 14,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
),
|
||||
|
|
@ -302,7 +302,7 @@ class _ChatAskAFriendEntryState extends State<ChatAskAFriendEntry> {
|
|||
? const SizedBox(
|
||||
width: 12,
|
||||
height: 12,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ class _ContactRowState extends State<_ContactRow> {
|
|||
const SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
Colors.white,
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
|
|||
SizedBox(
|
||||
width: 10,
|
||||
height: 10,
|
||||
child: CircularProgressIndicator(strokeWidth: 1, color: color),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 1, valueColor: AlwaysStoppedAnimation(color)),
|
||||
),
|
||||
const SizedBox(width: 2),
|
||||
],
|
||||
|
|
|
|||
|
|
@ -540,7 +540,7 @@ class _MediaViewerViewState extends State<MediaViewerView> {
|
|||
const SizedBox(
|
||||
width: 10,
|
||||
height: 10,
|
||||
child: CircularProgressIndicator(strokeWidth: 1),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 1),
|
||||
)
|
||||
else
|
||||
imageSaved
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ class _AddContactViaQrLinkViewState extends State<AddContactViaQrLinkView> {
|
|||
? const SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ class _SearchUsernameView extends State<AddNewUserView> {
|
|||
child: SizedBox(
|
||||
width: 18,
|
||||
height: 18,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
|
||||
),
|
||||
)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class FriendSuggestionsComp extends StatelessWidget {
|
|||
final contact = f.$1;
|
||||
final isSelected =
|
||||
selectedFriends.contains(contact.userId);
|
||||
return CheckboxListTile(
|
||||
return CheckboxListTile.adaptive(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(contact.displayName ?? contact.username),
|
||||
value: isSelected,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class _GroupCreateSelectGroupNameViewState
|
|||
? const SizedBox(
|
||||
width: 15,
|
||||
height: 15,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 1,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ class _StartNewChatView extends State<GroupCreateSelectMembersView> {
|
|||
contactId: user.userId,
|
||||
fontSize: 13,
|
||||
),
|
||||
trailing: Checkbox(
|
||||
trailing: Checkbox.adaptive(
|
||||
value:
|
||||
selectedUsers.contains(user.userId) |
|
||||
alreadyInGroup.contains(user.userId),
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ class SynchronizedViewerActionsToolbarComp extends StatelessWidget {
|
|||
? const SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
color: Colors.white,
|
||||
valueColor: AlwaysStoppedAnimation(Colors.white),
|
||||
),
|
||||
)
|
||||
: const FaIcon(
|
||||
|
|
|
|||
|
|
@ -409,7 +409,9 @@ class MemoriesViewState extends State<MemoriesView> {
|
|||
child: CircularProgressIndicator(
|
||||
value: state.migrationProgress,
|
||||
strokeWidth: 2.5,
|
||||
color: context.color.primary,
|
||||
valueColor: AlwaysStoppedAnimation(
|
||||
context.color.primary,
|
||||
),
|
||||
backgroundColor: context.color.primary
|
||||
.withValues(alpha: 0.2),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -219,8 +219,8 @@ class _BackupRecoveryViewState extends State<BackupRecoveryView> {
|
|||
? const SizedBox(
|
||||
height: 24,
|
||||
width: 24,
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
valueColor: AlwaysStoppedAnimation(Colors.white),
|
||||
strokeWidth: 3,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -299,8 +299,8 @@ class _RegisterViewState extends State<RegisterView> {
|
|||
? const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
valueColor: AlwaysStoppedAnimation(Colors.white),
|
||||
strokeWidth: 3,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ class NextButtonComp extends StatelessWidget {
|
|||
? const SizedBox(
|
||||
height: 24,
|
||||
width: 24,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class SetupSwitchCard extends StatelessWidget {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SwitchListTile(
|
||||
SwitchListTile.adaptive(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
title: Text(
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ class _RecoveryViewState extends State<RecoveryView> {
|
|||
? const SizedBox(
|
||||
height: 16,
|
||||
width: 16,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
|
||||
)
|
||||
: const Icon(Icons.restore_rounded),
|
||||
style: FilledButton.styleFrom(
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ class _SetupBackupViewState extends State<SetupBackupView> {
|
|||
? const SizedBox(
|
||||
height: 12,
|
||||
width: 12,
|
||||
child: CircularProgressIndicator(strokeWidth: 1),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 1),
|
||||
)
|
||||
: const Icon(Icons.lock_clock_rounded),
|
||||
label: Text(
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class _ChatSettingsViewState extends State<ChatSettingsView> {
|
|||
title: Text(context.lang.settingsPreSelectedReactions),
|
||||
onTap: () => context.push(Routes.settingsChatsReactions),
|
||||
),
|
||||
SwitchListTile(
|
||||
SwitchListTile.adaptive(
|
||||
title: Text(
|
||||
context
|
||||
.lang
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ class _AutoDownloadOptionsDialogState extends State<AutoDownloadOptionsDialog> {
|
|||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CheckboxListTile(
|
||||
CheckboxListTile.adaptive(
|
||||
title: const Text('Image'),
|
||||
value: autoDownloadOptions[widget.connectionMode.name]!.contains(
|
||||
DownloadMediaTypes.image.name,
|
||||
|
|
@ -222,7 +222,7 @@ class _AutoDownloadOptionsDialogState extends State<AutoDownloadOptionsDialog> {
|
|||
await _updateAutoDownloadSetting(DownloadMediaTypes.image, value);
|
||||
},
|
||||
),
|
||||
CheckboxListTile(
|
||||
CheckboxListTile.adaptive(
|
||||
title: const Text('Video'),
|
||||
value: autoDownloadOptions[widget.connectionMode.name]!.contains(
|
||||
DownloadMediaTypes.video.name,
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ class _ImportFromGalleryViewState extends State<ImportFromGalleryView> {
|
|||
|
||||
Widget _buildBody() {
|
||||
if (_isLoading) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
return const Center(child: CircularProgressIndicator.adaptive());
|
||||
}
|
||||
|
||||
if (!_hasPermission) {
|
||||
|
|
@ -530,7 +530,7 @@ class _ImportFromGalleryViewState extends State<ImportFromGalleryView> {
|
|||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const CircularProgressIndicator(),
|
||||
const CircularProgressIndicator.adaptive(),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
_importStatus,
|
||||
|
|
@ -600,7 +600,7 @@ class _GalleryThumbnailWidgetState extends State<GalleryThumbnailWidget> {
|
|||
child: SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@ class _DeveloperSettingsViewState extends State<DeveloperSettingsView> {
|
|||
? const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
|
||||
)
|
||||
: null,
|
||||
onTap: _isGeneratingMockImages
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ class _ChangeLogViewState extends State<ChangeLogView> {
|
|||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(context.lang.openChangeLog),
|
||||
Switch(
|
||||
Switch.adaptive(
|
||||
value: !userService.currentUser.hideChangeLog,
|
||||
onChanged: (_) => UserService.update(
|
||||
(u) => u.hideChangeLog = !u.hideChangeLog,
|
||||
|
|
|
|||
|
|
@ -243,9 +243,9 @@ $debugLogToken
|
|||
? SizedBox(
|
||||
height: 12,
|
||||
width: 12,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
color: Theme.of(context).colorScheme.inversePrimary,
|
||||
valueColor: AlwaysStoppedAnimation(Theme.of(context).colorScheme.inversePrimary),
|
||||
),
|
||||
)
|
||||
: const FaIcon(FontAwesomeIcons.angleRight),
|
||||
|
|
@ -291,7 +291,7 @@ class _IncludeDebugLogState extends State<IncludeDebugLog> {
|
|||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Checkbox(
|
||||
Checkbox.adaptive(
|
||||
value: widget.isChecked,
|
||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
onChanged: (value) {
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ class _FaqViewState extends State<FaqView> {
|
|||
appBar: AppBar(
|
||||
title: Text(context.lang.settingsHelpFAQ),
|
||||
),
|
||||
body: const Center(child: CircularProgressIndicator()),
|
||||
body: const Center(child: CircularProgressIndicator.adaptive()),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ class _NotificationViewState extends State<NotificationView> {
|
|||
? const SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
|
|
@ -138,7 +138,7 @@ class _NotificationViewState extends State<NotificationView> {
|
|||
? const SizedBox(
|
||||
width: 16,
|
||||
height: 16,
|
||||
child: CircularProgressIndicator(
|
||||
child: CircularProgressIndicator.adaptive(
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class UserList extends StatelessWidget {
|
|||
],
|
||||
),
|
||||
leading: AvatarIcon(contactId: user.userId, fontSize: 15),
|
||||
trailing: Checkbox(
|
||||
trailing: Checkbox.adaptive(
|
||||
value: user.blocked,
|
||||
onChanged: (value) async {
|
||||
await block(context, user.userId, value);
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ class UserDiscoverySetupComp extends StatelessWidget {
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SwitchListTile(
|
||||
SwitchListTile.adaptive(
|
||||
value: state.isUserDiscoveryEnabled,
|
||||
onChanged: (val) => state.update(() {
|
||||
state.isUserDiscoveryEnabled = val;
|
||||
|
|
@ -323,7 +323,7 @@ class UserDiscoverySetupComp extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
SwitchListTile(
|
||||
SwitchListTile.adaptive(
|
||||
value: state.isManualApprovalEnabled,
|
||||
onChanged: (val) => state.update(
|
||||
() => state.isManualApprovalEnabled = val,
|
||||
|
|
@ -547,7 +547,7 @@ class UserDiscoverySetupComp extends StatelessWidget {
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
SwitchListTile(
|
||||
SwitchListTile.adaptive(
|
||||
value: state.sharePromotion,
|
||||
onChanged: (val) => state.update(() {
|
||||
state.sharePromotion = val;
|
||||
|
|
|
|||
|
|
@ -195,7 +195,7 @@ class _SelectAdditionalUsers extends State<SelectAdditionalUsers> {
|
|||
contactId: user.userId,
|
||||
fontSize: 13,
|
||||
),
|
||||
trailing: Checkbox(
|
||||
trailing: Checkbox.adaptive(
|
||||
value:
|
||||
selectedUsers.contains(user.userId) |
|
||||
_alreadySelected.contains(user.userId),
|
||||
|
|
|
|||
|
|
@ -330,7 +330,7 @@ class _PlanCardState extends State<PlanCard> {
|
|||
? const SizedBox(
|
||||
width: 10,
|
||||
height: 10,
|
||||
child: CircularProgressIndicator(strokeWidth: 1),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 1),
|
||||
)
|
||||
: null,
|
||||
label: Text(
|
||||
|
|
@ -350,7 +350,7 @@ class _PlanCardState extends State<PlanCard> {
|
|||
? const SizedBox(
|
||||
width: 10,
|
||||
height: 10,
|
||||
child: CircularProgressIndicator(strokeWidth: 1),
|
||||
child: CircularProgressIndicator.adaptive(strokeWidth: 1),
|
||||
)
|
||||
: null,
|
||||
label: Text(
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ class _SelectAdditionalUsers extends State<SelectContactsView> {
|
|||
contactId: user.userId,
|
||||
fontSize: 13,
|
||||
),
|
||||
trailing: Checkbox(
|
||||
trailing: Checkbox.adaptive(
|
||||
value:
|
||||
selectedUsers.contains(user.userId) |
|
||||
_alreadySelected.contains(user.userId),
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ class _UserStudyQuestionnaireViewState
|
|||
'Welche der folgenden Messenger hast du schon einmal benutzt?',
|
||||
),
|
||||
..._messengerOptions.map(
|
||||
(m) => CheckboxListTile(
|
||||
(m) => CheckboxListTile.adaptive(
|
||||
title: Text(m),
|
||||
visualDensity: const VisualDensity(vertical: -4),
|
||||
value: (_responses['messengers'] as List<dynamic>).contains(m),
|
||||
|
|
|
|||
Loading…
Reference in a new issue