Screens / forms
Contact support
Lets people write to support with a subject, a reference, a bounded message and attachments, sent only once even without an answer, then follow the request and read the latest reply.
Import
Contact support is part of Fliin Pro. With a license key, sign in once with fliin login, then add it in a Flutter app where fliin init has run:
fliin login
fliin add contact-supportAlso installs: core, alert, app-bar, button, empty-state, field, page, section-header, select, skeleton, surface, text-field, text, tracking-steps, spinner, icons, result-card
Examples
Form
An empty request: topic, message and attachments. standalone holds the form over the ContactSupportService you pass.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
class ContactSupportFormExample extends StatelessWidget {
const ContactSupportFormExample({super.key});
@override
Widget build(BuildContext context) {
return ContactSupportScreen.standalone(
service: SampleContactSupportService(latency: const Duration(milliseconds: 900)),
initial: const ContactSupportForm(sampleSupportTopics, SupportDraft()),
now: () => DateTime(2026, 10, 24, 10),
onBack: () {},
);
}
}Filled
A request ready to send, its topic chosen and its message written.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
class ContactSupportFilledExample extends StatelessWidget {
const ContactSupportFilledExample({super.key});
@override
Widget build(BuildContext context) {
return ContactSupportScreen.standalone(
service: SampleContactSupportService(latency: const Duration(milliseconds: 900)),
initial: const ContactSupportForm(sampleSupportTopics, sampleSupportDraft),
now: () => DateTime(2026, 10, 24, 10),
onBack: () {},
);
}
}Unconfirmed
The connection dropped while sending: the screen cannot tell whether the request arrived, and sending again reuses the same attemptKey so it is never duplicated.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
class ContactSupportUnconfirmedExample extends StatelessWidget {
const ContactSupportUnconfirmedExample({super.key});
@override
Widget build(BuildContext context) {
return ContactSupportScreen.standalone(
service: SampleContactSupportService(latency: const Duration(milliseconds: 900)),
initial: const ContactSupportForm(
sampleSupportTopics,
sampleSupportDraft,
attemptKey: 'support-example',
unconfirmed: true,
notice: ContactSupportNotice.unconfirmed,
),
now: () => DateTime(2026, 10, 24, 10),
onBack: () {},
);
}
}Tracking
A request already sent, followed step by step until support answers.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
class ContactSupportTrackingExample extends StatelessWidget {
const ContactSupportTrackingExample({super.key});
@override
Widget build(BuildContext context) {
return ContactSupportScreen.standalone(
service: SampleContactSupportService(latency: const Duration(milliseconds: 900)),
initial: ContactSupportTracking(sampleSupportRequest),
now: () => DateTime(2026, 10, 24, 10),
onBack: () {},
);
}
}Received
Just after sending: the request is tracked, under a notice that it was received.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
class ContactSupportReceivedExample extends StatelessWidget {
const ContactSupportReceivedExample({super.key});
@override
Widget build(BuildContext context) {
return ContactSupportScreen.standalone(
service: SampleContactSupportService(latency: const Duration(milliseconds: 900)),
initial: ContactSupportTracking(sampleReceivedSupportRequest, notice: ContactSupportTrackingNotice.sent),
now: () => DateTime(2026, 10, 24, 10),
onBack: () {},
);
}
}Loading
While the topics load, skeletons keep the place of the form.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
class ContactSupportLoadingExample extends StatelessWidget {
const ContactSupportLoadingExample({super.key});
@override
Widget build(BuildContext context) {
return ContactSupportScreen.standalone(
service: SampleContactSupportService(latency: const Duration(milliseconds: 900)),
initial: const ContactSupportLoading(),
now: () => DateTime(2026, 10, 24, 10),
onBack: () {},
);
}
}Error
When loading fails, the screen says so and offers to try again.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
class ContactSupportErrorExample extends StatelessWidget {
const ContactSupportErrorExample({super.key});
@override
Widget build(BuildContext context) {
return ContactSupportScreen.standalone(
service: SampleContactSupportService(latency: const Duration(milliseconds: 900)),
initial: const ContactSupportFailed(),
now: () => DateTime(2026, 10, 24, 10),
onBack: () {},
);
}
}Offline
Without a connection, the screen asks to reconnect before writing a request.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
class ContactSupportOfflineExample extends StatelessWidget {
const ContactSupportOfflineExample({super.key});
@override
Widget build(BuildContext context) {
return ContactSupportScreen.standalone(
service: SampleContactSupportService(latency: const Duration(milliseconds: 900)),
initial: const ContactSupportOffline(),
now: () => DateTime(2026, 10, 24, 10),
onBack: () {},
);
}
}Channels
The other ways to reach you above the form (header), and no order field for an app without orders (showReference: false).
import 'package:your_app/ui/fliin/components/list_row/fl_list_row.dart';
import 'package:your_app/ui/fliin/core/fliin.dart';
import 'package:your_app/ui/fliin/icons/fl_icons.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
class ContactSupportChannelsExample extends StatelessWidget {
const ContactSupportChannelsExample({super.key});
@override
Widget build(BuildContext context) {
return ContactSupportScreen.standalone(
service: SampleContactSupportService(latency: const Duration(milliseconds: 900)),
initial: const ContactSupportForm(sampleSupportTopics, SupportDraft()),
now: () => DateTime(2026, 10, 24, 10),
showReference: false,
header: FlListGroup(
children: [
FlListRow(
leading: FlIcon(FlIcons.comment),
title: 'Chat with us',
subtitle: 'Replies in about 5 minutes',
trailing: const FlListRowChevron(),
onPressed: () {},
),
FlListRow(leading: FlIcon(FlIcons.clock), title: 'Monday to Friday, 9 am to 6 pm', subtitle: 'Opening hours'),
],
),
onBack: () {},
onAddAttachment: () async => null,
);
}
}Routing
fliin add contact-support prints the route for the router it finds in your pubspec, a file next to the page that wires its navigation. Each of them:
go_router
// lib/contact_support_route.dart, next to contact_support_page.dart.
import 'package:go_router/go_router.dart';
import 'contact_support_page.dart';
/// Add contactSupportRoute to the routes of your GoRouter.
final contactSupportRoute = GoRoute(
path: '/support',
builder: (context, state) => ContactSupportPage(
requestId: state.uri.queryParameters['request'],
// Alone in the stack (deep link, go): your app's home.
onBack: () => context.canPop() ? context.pop() : context.go('/'),
),
);navigator
// lib/contact_support_route.dart, next to contact_support_page.dart.
import 'package:flutter/material.dart';
import 'contact_support_page.dart';
/// Opens “Contact support”: `Navigator.of(context).push(contactSupportRoute())`.
Route<void> contactSupportRoute({String? requestId}) => MaterialPageRoute<void>(
builder: (context) => ContactSupportPage(
requestId: requestId,
onBack: () => Navigator.of(context).maybePop(),
),
);State
The controller is a ChangeNotifier from widgets.dart, with no package. fliin add contact-support prints the page that holds it with the state management it finds, its imports written for your package; below they read your_app. Your backend implements the Service interface of the screen's _data.dart file:
none
// lib/contact_support_page.dart
// Your backend: implement ContactSupportService (contact_support_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
// The app's service lives above the routes: a request sent and then
// left midway is found again when the screen reopens.
final contactSupportService = SampleContactSupportService();
class ContactSupportPage extends StatelessWidget {
const ContactSupportPage({
super.key,
this.requestId,
required this.onBack,
});
final String? requestId;
final VoidCallback onBack;
@override
Widget build(BuildContext context) => ContactSupportScreen.standalone(
key: ValueKey(requestId),
service: contactSupportService,
requestId: requestId,
onBack: onBack,
);
}provider
// lib/contact_support_page.dart
// Your backend: implement ContactSupportService (contact_support_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
import 'package:provider/provider.dart';
// The app's service lives above the routes: a request sent and then
// left midway is found again when the screen reopens.
final contactSupportService = SampleContactSupportService();
class ContactSupportPage extends StatelessWidget {
const ContactSupportPage({
super.key,
this.requestId,
required this.onBack,
});
final String? requestId;
final VoidCallback onBack;
@override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (_) => ContactSupportController(service: contactSupportService, requestId: requestId)..load(),
child: Builder(
builder: (context) => ContactSupportScreen(
controller: context.read<ContactSupportController>(),
onBack: onBack,
),
),
);
}riverpod
// lib/contact_support_page.dart
// Your backend: implement ContactSupportService (contact_support_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// The app's service lives above the routes: a request sent and then
// left midway is found again when the screen reopens.
final contactSupportService = SampleContactSupportService();
final contactSupportControllerProvider = Provider.autoDispose.family<ContactSupportController, String?>((ref, requestId) {
final controller = ContactSupportController(service: contactSupportService, requestId: requestId)..load();
ref.onDispose(controller.dispose);
return controller;
});
class ContactSupportPage extends ConsumerWidget {
const ContactSupportPage({
super.key,
this.requestId,
required this.onBack,
});
final String? requestId;
final VoidCallback onBack;
@override
Widget build(BuildContext context, WidgetRef ref) => ContactSupportScreen(
controller: ref.watch(contactSupportControllerProvider(requestId)),
onBack: onBack,
);
}bloc
// lib/contact_support_page.dart
// Your backend: implement ContactSupportService (contact_support_data.dart) and pass it instead of the sample service.
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_controller.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_data.dart';
import 'package:your_app/ui/fliin/screens/contact_support/contact_support_screen.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// The app's service lives above the routes: a request sent and then
// left midway is found again when the screen reopens.
final contactSupportService = SampleContactSupportService();
/// The screen's controller as a bloc, for your BlocListener and BlocBuilder:
/// one emission per controller notification. `version` tells them apart
/// when `state` does not change (mode, filters, text…, read them on
/// `controller`). The screen listens to the controller itself.
class ContactSupportCubit extends Cubit<({ContactSupportState state, int version})> {
ContactSupportCubit(this.controller) : super((state: controller.state, version: 0)) {
controller.addListener(_changed);
}
final ContactSupportController controller;
void _changed() => emit((state: controller.state, version: state.version + 1));
@override
Future<void> close() {
controller
..removeListener(_changed)
..dispose();
return super.close();
}
}
class ContactSupportPage extends StatelessWidget {
const ContactSupportPage({
super.key,
this.requestId,
required this.onBack,
});
final String? requestId;
final VoidCallback onBack;
@override
Widget build(BuildContext context) => BlocProvider(
create: (_) => ContactSupportCubit(ContactSupportController(service: contactSupportService, requestId: requestId)..load()),
child: Builder(
builder: (context) => ContactSupportScreen(
controller: context.read<ContactSupportCubit>().controller,
onBack: onBack,
),
),
);
}API
ContactSupportScreen: class extends StatefulWidget
ContactSupportScreen.new: const new({super.key, required ContactSupportController controller, DateTime Function()? now, SupportDateFormat? formatDate, VoidCallback? onBack, Future<SupportAttachment?> Function()? onAddAttachment, ValueChanged<SupportRequest>? onSent, bool showReference, Widget? header})
ContactSupportScreen.standalone: const new({super.key, required ContactSupportService service, String? requestId, ContactSupportState? initial, DateTime Function()? now, SupportDateFormat? formatDate, VoidCallback? onBack, Future<SupportAttachment?> Function()? onAddAttachment, ValueChanged<SupportRequest>? onSent, bool showReference, Widget? header})
ContactSupportScreen.controller: get ContactSupportController?
ContactSupportScreen.service: get ContactSupportService?
ContactSupportScreen.requestId: get String?
ContactSupportScreen.initial: get ContactSupportState?
ContactSupportScreen.now: get DateTime Function()?
ContactSupportScreen.formatDate: get SupportDateFormat?
ContactSupportScreen.onBack: get VoidCallback?
ContactSupportScreen.onAddAttachment: get Future<SupportAttachment?> Function()?
ContactSupportScreen.onSent: get ValueChanged<SupportRequest>?
ContactSupportScreen.showReference: get bool
ContactSupportScreen.header: get Widget?
ContactSupportScreen.createState: State<ContactSupportScreen>()
ContactSupportState: sealed class permits {ContactSupportFailed, ContactSupportForm, ContactSupportLoading, ContactSupportOffline, ContactSupportTracking}
ContactSupportState.new: const new()
ContactSupportLoading: final class extends ContactSupportState
ContactSupportLoading.new: const new()
ContactSupportFailed: final class extends ContactSupportState
ContactSupportFailed.new: const new()
ContactSupportOffline: final class extends ContactSupportState
ContactSupportOffline.new: const new()
ContactSupportBusy: enum {sending, checking}
ContactSupportBusy.sending: static final ContactSupportBusy
ContactSupportBusy.checking: static final ContactSupportBusy
ContactSupportNotice: enum {notSent, rejected, unconfirmed, notReceived, stillUnknown, checkOffline, checkFailed}
ContactSupportNotice.notSent: static final ContactSupportNotice
ContactSupportNotice.rejected: static final ContactSupportNotice
ContactSupportNotice.unconfirmed: static final ContactSupportNotice
ContactSupportNotice.notReceived: static final ContactSupportNotice
ContactSupportNotice.stillUnknown: static final ContactSupportNotice
ContactSupportNotice.checkOffline: static final ContactSupportNotice
ContactSupportNotice.checkFailed: static final ContactSupportNotice
ContactSupportForm: final class extends ContactSupportState
ContactSupportForm.new: const new(List<SupportTopic> topics, SupportDraft draft, {String? attemptKey, bool unconfirmed, ContactSupportBusy? busy, ContactSupportNotice? notice})
ContactSupportForm.topics: get List<SupportTopic>
ContactSupportForm.draft: get SupportDraft
ContactSupportForm.attemptKey: get String?
ContactSupportForm.unconfirmed: get bool
ContactSupportForm.busy: get ContactSupportBusy?
ContactSupportForm.notice: get ContactSupportNotice?
ContactSupportForm.editable: get bool
ContactSupportTrackingNotice: enum {sent, refreshFailed, refreshOffline}
ContactSupportTrackingNotice.sent: static final ContactSupportTrackingNotice
ContactSupportTrackingNotice.refreshFailed: static final ContactSupportTrackingNotice
ContactSupportTrackingNotice.refreshOffline: static final ContactSupportTrackingNotice
ContactSupportTracking: final class extends ContactSupportState
ContactSupportTracking.new: const new(SupportRequest request, {bool refreshing, ContactSupportTrackingNotice? notice})
ContactSupportTracking.request: get SupportRequest
ContactSupportTracking.refreshing: get bool
ContactSupportTracking.notice: get ContactSupportTrackingNotice?
ContactSupportController: class extends ChangeNotifier
ContactSupportController.new: new({required ContactSupportService service, String? requestId, ContactSupportState initial, String Function()? newKey})
ContactSupportController.service: get ContactSupportService
ContactSupportController.requestId: get String?
ContactSupportController.newKey: get String Function()
ContactSupportController.state: get ContactSupportState
ContactSupportController.load: Future<bool>()
ContactSupportController.edit: bool(SupportDraft draft)
ContactSupportController.submit: Future<bool>()
ContactSupportController.check: Future<bool>()
ContactSupportController.refresh: Future<bool>()
ContactSupportController.dispose: void()
SupportTopic: final class
SupportTopic.new: const new({required String id, required String label})
SupportTopic.id: get String
SupportTopic.label: get String
SupportAttachment: final class
SupportAttachment.new: const new({required String id, required String name, ImageProvider? preview})
SupportAttachment.id: get String
SupportAttachment.name: get String
SupportAttachment.preview: get ImageProvider?
SupportAttachment.operator ==: bool(Object other)
SupportAttachment.hashCode: get int
supportMessageMax: const dynamic
supportReferenceMax: const dynamic
SupportDraft: final class
SupportDraft.new: const new({String? topicId, String reference, String message, List<SupportAttachment> attachments})
SupportDraft.topicId: get String?
SupportDraft.reference: get String
SupportDraft.message: get String
SupportDraft.attachments: get List<SupportAttachment>
SupportDraft.copyWith: SupportDraft({String? topicId, String? reference, String? message, List<SupportAttachment>? attachments})
SupportDraft.operator ==: bool(Object other)
SupportDraft.hashCode: get int
SupportDraft.issues: get Set<SupportIssue>
SupportIssue: enum {topicMissing, referenceTooLong, messageMissing, messageTooLong}
SupportIssue.topicMissing: static final SupportIssue
SupportIssue.referenceTooLong: static final SupportIssue
SupportIssue.messageMissing: static final SupportIssue
SupportIssue.messageTooLong: static final SupportIssue
SupportStep: enum {received, inProgress, answered, closed}
SupportStep.received: static final SupportStep
SupportStep.inProgress: static final SupportStep
SupportStep.answered: static final SupportStep
SupportStep.closed: static final SupportStep
SupportReply: final class
SupportReply.new: const new({required String author, required DateTime at, required String text})
SupportReply.author: get String
SupportReply.at: get DateTime
SupportReply.text: get String
SupportRequest: final class
SupportRequest.new: new({required String id, required String number, required String topic, required Map<SupportStep, DateTime> reached, SupportReply? reply})
SupportRequest.id: get String
SupportRequest.number: get String
SupportRequest.topic: get String
SupportRequest.reached: get Map<SupportStep, DateTime>
SupportRequest.reply: get SupportReply?
SupportRequest.step: get SupportStep
SupportAttempt: final class
SupportAttempt.new: const new({required String key, required SupportDraft draft, SupportRequest? received})
SupportAttempt.key: get String
SupportAttempt.draft: get SupportDraft
SupportAttempt.received: get SupportRequest?
SupportForm: final class
SupportForm.new: const new({required List<SupportTopic> topics, SupportAttempt? pending})
SupportForm.topics: get List<SupportTopic>
SupportForm.pending: get SupportAttempt?
SupportLookup: sealed class permits {SupportFound, SupportNotFound, SupportStillPending}
SupportLookup.new: const new()
SupportFound: final class extends SupportLookup
SupportFound.new: const new(SupportRequest request)
SupportFound.request: get SupportRequest
SupportNotFound: final class extends SupportLookup
SupportNotFound.new: const new()
SupportStillPending: final class extends SupportLookup
SupportStillPending.new: const new()
SupportNoNetwork: final class implements Exception
SupportNoNetwork.new: const new()
SupportNotSent: final class implements Exception
SupportNotSent.new: const new()
SupportUnknownRequest: final class implements Exception
SupportUnknownRequest.new: const new(String id)
SupportUnknownRequest.id: get String
SupportUnknownRequest.toString: String()
SupportRejected: final class implements Exception
SupportRejected.new: const new()
ContactSupportService: abstract interface class
ContactSupportService.new: new()
ContactSupportService.form: abstract Future<SupportForm>()
ContactSupportService.submit: abstract Future<SupportRequest>(SupportDraft draft, {required String key})
ContactSupportService.find: abstract Future<SupportLookup>(String key)
ContactSupportService.request: abstract Future<SupportRequest>(String id)
ContactSupportService.acknowledge: abstract void(String key)
sampleSupportTopics: const dynamic
sampleSupportDraft: const dynamic
sampleSupportRequest: get dynamic
sampleReceivedSupportRequest: get dynamic
SampleContactSupportService: final class implements ContactSupportService
SampleContactSupportService.new: new({Duration latency, bool offline, bool losesResponse, bool rejects, SupportAttempt? pending})
SampleContactSupportService.latency: get Duration
SampleContactSupportService.offline: get bool
SampleContactSupportService.offline=: set bool
SampleContactSupportService.losesResponse: get bool
SampleContactSupportService.losesResponse=: set bool
SampleContactSupportService.rejects: get bool
SampleContactSupportService.rejects=: set bool
SampleContactSupportService.keys: get List<String>
SampleContactSupportService.pending: get SupportAttempt?
SampleContactSupportService.pending=: set SupportAttempt?
SampleContactSupportService.form: Future<SupportForm>()
SampleContactSupportService.submit: Future<SupportRequest>(SupportDraft draft, {required String key})
SampleContactSupportService.find: Future<SupportLookup>(String key)
SampleContactSupportService.request: Future<SupportRequest>(String id)
SampleContactSupportService.acknowledge: void(String key)
SupportDateFormat: typedef = String Function(DateTime date, Locale locale)
contactSupportL10n: const Map<String, Map<String, String>>
ContactSupportStrings: final class
ContactSupportStrings.new: const new(String language, {required DateTime now, SupportDateFormat? format})
ContactSupportStrings.of: factory new(BuildContext context, {required DateTime now, SupportDateFormat? format})
ContactSupportStrings.language: get String
ContactSupportStrings.now: get DateTime
ContactSupportStrings.format: get SupportDateFormat?
ContactSupportStrings.digits: String(int n)
ContactSupportStrings.date: String(DateTime date)
ContactSupportStrings.when: String(DateTime date)
ContactSupportStrings.day: String(DateTime date)
ContactSupportStrings.title: get String
ContactSupportStrings.trackingTitle: get String
ContactSupportStrings.back: get String
ContactSupportStrings.loading: get String
ContactSupportStrings.refresh: get String
ContactSupportStrings.intro: get String
ContactSupportStrings.send: get String
ContactSupportStrings.topic: get String
ContactSupportStrings.topicPlaceholder: get String
ContactSupportStrings.close: get String
ContactSupportStrings.topicMissing: get String
ContactSupportStrings.reference: get String
ContactSupportStrings.referenceTooLong: get String
ContactSupportStrings.message: get String
ContactSupportStrings.messagePlaceholder: get String
ContactSupportStrings.messageCount: String(int count)
ContactSupportStrings.messageMissing: get String
ContactSupportStrings.messageTooLong: get String
ContactSupportStrings.attachments: get String
ContactSupportStrings.addAttachment: get String
ContactSupportStrings.removeAttachment: String(String name)
ContactSupportStrings.noticeNotSent: get String
ContactSupportStrings.noticeRejected: get String
ContactSupportStrings.noticeUnconfirmed: get String
ContactSupportStrings.noticeNotReceived: get String
ContactSupportStrings.noticeStillUnknown: get String
ContactSupportStrings.noticeCheckOffline: get String
ContactSupportStrings.noticeCheckFailed: get String
ContactSupportStrings.noticeSent: get String
ContactSupportStrings.noticeRefreshFailed: get String
ContactSupportStrings.noticeRefreshOffline: get String
ContactSupportStrings.check: get String
ContactSupportStrings.checking: get String
ContactSupportStrings.number: String(String number)
ContactSupportStrings.subject: String(String topic)
ContactSupportStrings.sentOn: String(DateTime date)
ContactSupportStrings.tracking: get String
ContactSupportStrings.trackingLabel: get String
ContactSupportStrings.step: String(SupportStep step)
ContactSupportStrings.current: get String
ContactSupportStrings.upcoming: get String
ContactSupportStrings.stepSpoken: String(int index, int count, List<String> parts)
ContactSupportStrings.reply: get String
ContactSupportStrings.replyFrom: String(String author, DateTime date)
ContactSupportStrings.noReply: get String
ContactSupportStrings.errorTitle: get String
ContactSupportStrings.errorMessage: get String
ContactSupportStrings.offlineTitle: get String
ContactSupportStrings.offlineMessage: get String
ContactSupportStrings.retry: get StringStrings
Every label in English, French and Arabic. The screen follows the closest Localizations; the same table is in the manifest, ready for your ARB files.
| Key | en | fr | ar |
|---|---|---|---|
contactSupportTitle | Contact support | Contacter le support | التواصل مع الدعم |
contactSupportTrackingTitle | Your request | Votre demande | طلبك |
contactSupportBack | Back | Retour | رجوع |
contactSupportLoading | Loading | Chargement | جارٍ التحميل |
contactSupportRefresh | Refresh the request | Actualiser la demande | تحديث الطلب |
contactSupportIntro | Tell us what is going on. Our team will answer you here. | Dites-nous ce qui se passe. Notre équipe vous répondra ici. | أخبرنا بما يحدث، وسيرد عليك فريقنا هنا. |
contactSupportSend | Send | Envoyer | إرسال |
contactSupportTopic | Subject | Sujet | الموضوع |
contactSupportTopicPlaceholder | Choose a subject | Choisissez un sujet | اختر موضوعًا |
contactSupportClose | Close | Fermer | إغلاق |
contactSupportTopicMissing | Choose a subject. | Choisissez un sujet. | اختر موضوعًا. |
contactSupportReference | Order or reference (optional) | Commande ou référence (facultatif) | الطلب أو المرجع (اختياري) |
contactSupportReferenceTooLong | {max} characters at most. | {max} caractères au plus. | {max} حرفًا على الأكثر. |
contactSupportMessage | Message | Message | الرسالة |
contactSupportMessagePlaceholder | Describe your problem | Décrivez votre problème | صف مشكلتك |
contactSupportMessageCount | {count} of {max} characters | {count} sur {max} caractères | {count} من {max} حرف |
contactSupportMessageMissing | Write your message. | Écrivez votre message. | اكتب رسالتك. |
contactSupportMessageTooLong | Your message is too long. | Votre message est trop long. | رسالتك طويلة جدًا. |
contactSupportAttachments | Attachments | Pièces jointes | المرفقات |
contactSupportAddAttachment | Add an attachment | Ajouter une pièce jointe | إضافة مرفق |
contactSupportRemoveAttachment | Remove {name} | Retirer {name} | إزالة {name} |
contactSupportNoticeNotSent | You are offline: nothing was sent. Your message is kept, try again. | Vous êtes hors ligne : rien n’est parti. Votre message est gardé, réessayez. | أنت غير متصل، ولم يُرسل شيء. رسالتك محفوظة، أعد المحاولة. |
contactSupportNoticeRejected | Support could not accept your request. Your message is kept, try again later. | Le support n’a pas pu accepter votre demande. Votre message est gardé, réessayez plus tard. | تعذّر على الدعم قبول طلبك. رسالتك محفوظة، أعد المحاولة لاحقًا. |
contactSupportNoticeUnconfirmed | Your request could not be confirmed. It may have arrived: check it before sending it again. | Votre demande n’a pas pu être confirmée. Elle est peut-être arrivée : vérifiez-la avant de la renvoyer. | تعذّر تأكيد طلبك، وربما وصل بالفعل. تحقّق منه قبل إرساله مجددًا. |
contactSupportNoticeNotReceived | Your request did not arrive. You can send it again. | Votre demande n’est pas arrivée. Vous pouvez la renvoyer. | لم يصل طلبك. يمكنك إرساله مجددًا. |
contactSupportNoticeStillUnknown | We still do not know whether your request arrived. Check again in a moment. | On ne sait pas encore si votre demande est arrivée. Vérifiez de nouveau dans un instant. | لا نعرف بعد إن كان طلبك قد وصل. تحقّق مجددًا بعد قليل. |
contactSupportNoticeCheckOffline | You are offline: the request could not be checked. | Vous êtes hors ligne : la demande n’a pas pu être vérifiée. | أنت غير متصل، وتعذّر التحقق من الطلب. |
contactSupportNoticeCheckFailed | The request could not be checked. Try again. | La demande n’a pas pu être vérifiée. Réessayez. | تعذّر التحقق من الطلب. أعد المحاولة. |
contactSupportCheck | Check the request | Vérifier la demande | التحقق من الطلب |
contactSupportChecking | Checking the request | Vérification de la demande | جارٍ التحقق من الطلب |
contactSupportNumber | Request {number} | Demande {number} | الطلب {number} |
contactSupportSubject | Subject: {topic} | Sujet : {topic} | الموضوع: {topic} |
contactSupportSentOn | Sent {date} | Envoyée {date} | أُرسل {date} |
contactSupportNoticeSent | Your request has been received. | Votre demande est bien reçue. | تم استلام طلبك. |
contactSupportNoticeRefreshFailed | The request could not be refreshed. | La demande n’a pas pu être actualisée. | تعذّر تحديث الطلب. |
contactSupportNoticeRefreshOffline | You are offline. The request could not be refreshed. | Vous êtes hors ligne : la demande n’a pas pu être actualisée. | أنت غير متصل، وتعذّر تحديث الطلب. |
contactSupportTracking | Follow-up | Suivi | المتابعة |
contactSupportTrackingLabel | Request follow-up | Suivi de la demande | متابعة الطلب |
contactSupportStepReceived | Received | Reçue | تم الاستلام |
contactSupportStepInProgress | In progress | En traitement | قيد المعالجة |
contactSupportStepAnswered | Answered | Répondue | تم الرد |
contactSupportStepClosed | Closed | Close | مغلق |
contactSupportStepCurrent | Current | En cours | الحالية |
contactSupportStepUpcoming | Upcoming | À venir | قادمة |
contactSupportStepOf | Step {index} of {count} | Étape {index} sur {count} | الخطوة {index} من {count} |
contactSupportSeparator | , | , | ، |
contactSupportReply | Latest reply | Dernière réponse | آخر رد |
contactSupportReplyFrom | {author} · {date} | {author} · {date} | {author} · {date} |
contactSupportNoReply | No reply yet. | Pas encore de réponse. | لا رد بعد. |
contactSupportDateOn | on {date} | le {date} | في {date} |
contactSupportToday | today | aujourd’hui | اليوم |
contactSupportYesterday | yesterday | hier | أمس |
contactSupportTodayTitle | Today | Aujourd’hui | اليوم |
contactSupportYesterdayTitle | Yesterday | Hier | أمس |
contactSupportDate | {month} {day} | {day} {month} | {day} {month} |
contactSupportDateYear | {month} {day}, {year} | {day} {month} {year} | {day} {month} {year} |
contactSupportMonths | January,February,March,April,May,June,July,August,September,October,November,December | janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre | يناير,فبراير,مارس,أبريل,مايو,يونيو,يوليو,أغسطس,سبتمبر,أكتوبر,نوفمبر,ديسمبر |
contactSupportErrorTitle | Contact unavailable | Contact indisponible | التواصل غير متاح |
contactSupportErrorMessage | Something went wrong. Try again in a moment. | Un problème est survenu. Réessayez dans un instant. | حدث خطأ. أعد المحاولة بعد قليل. |
contactSupportOfflineTitle | You are offline | Vous êtes hors ligne | أنت غير متصل |
contactSupportOfflineMessage | Connect to write to support. | Connectez-vous pour écrire au support. | اتصل لمراسلة الدعم. |
contactSupportRetry | Try again | Réessayer | أعد المحاولة |
Reference renders
The 16 images published with version 0.2.5, rendered by the shared harness on macOS with Flutter 3.47.7. Each shows every state side by side, at the size of an iPhone (390 × 844) or of an Android phone (412 × 915). fliin verify contact-support compares your copy to them.
















Use it to
- open a ticket with customer service
- show where a support ticket stands
- show the latest answer from support
- offer to check an unconfirmed ticket
- add a screenshot to a support ticket
- Not for
- frequently asked questions and their search: use the help center (help-center)
- tracking a purchase and its delivery: use order tracking (order)
- States