fix: every text field has a limit, and long names no longer overflow
A Pomodoro profile's name could be as long as one liked, and pushed the Home card's header beyond the window. Of 56 fields, only release notes and a licence's year had a limit. Limits by what a field holds (core/widget/text_limits.dart, decided 2026-10-11): a name shown in a menu or on a chip 40 (Pomodoro profiles, tags, a study button's label); a secondary title or a reading above characters 60; a title 120 (studysets, notes, paths, steps, PDFs, callouts, a video's caption, a licence's holder); an answer or item 200 (meanings, readings, glosses, options, categories, gaps, typed answers); a search 200; a part of a citation 500; a message 2000 (reports, replies, questions to Claude); a web address 2000; a passage with gaps or a formula 5000. The public profile and a published studyset's name take the instance's own limits (display name 30, handle 30, bio 500, links 2000, name 50), which the app didn't say before. Pasted flashcards to import and numbers have none. Fields count only from 80 % of their limit. Text can still be longer where it came from elsewhere (an older app, an import, a release), so the places showing it cut it short: the Pomodoro card's header and its profiles. A test shows names beyond every limit on Home, the library, a studyset's screen with its tabs and topics, the card browser with its tags, and a session, on a phone and a desktop: none overflows (it fails on the Pomodoro card as it was). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MMm7usAo6q9ZZRoPkWjoxi Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
e459c972a4
commit
e32a3129f6
38 changed files with 500 additions and 42 deletions
|
|
@ -2,6 +2,7 @@ import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/citation/model/source.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/adaptive_sheet.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/confirm_dialog.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// Asks for a source's parts: a new one, or [source] changed. Completes with
|
||||
|
|
@ -100,6 +101,8 @@ class _SourceSheetState() extends State<_SourceSheet> {
|
|||
}) => Padding(
|
||||
padding: const EdgeInsets.only(top: 16),
|
||||
child: TextField(
|
||||
maxLength: TextLimits.reference,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: controller,
|
||||
keyboardType: multiline ? TextInputType.multiline : keyboardType,
|
||||
minLines: 1,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/content/content_blocks.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/editor/editor_blocks.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/theme/theme_extras.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
|
|
@ -411,6 +412,8 @@ class _TitleDialogState() extends State<_TitleDialog> {
|
|||
return AlertDialog(
|
||||
title: Text(l10n.calloutTitleDialog),
|
||||
content: TextField(
|
||||
maxLength: TextLimits.title,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _field,
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:flutter_math_fork/flutter_math.dart';
|
|||
import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/editor/math_view.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/layout/readable_width.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// Edits a formula in LaTeX in the whole window, previewed as it is typed,
|
||||
|
|
@ -165,6 +166,8 @@ class _FormulaScreenState() extends State<_FormulaScreen> {
|
|||
),
|
||||
const SizedBox(height: 16),
|
||||
TextField(
|
||||
maxLength: TextLimits.passage,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _field,
|
||||
focusNode: _focus,
|
||||
autofocus: true,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import 'package:appflowy_editor/appflowy_editor.dart';
|
|||
import 'package:flutter/gestures.dart';
|
||||
import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/content/content_blocks.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
// Furigana (ruby): the reading of text within a line, kept on the text's
|
||||
|
|
@ -223,6 +224,8 @@ class _ReadingDialogState() extends State<_ReadingDialog> {
|
|||
return AlertDialog(
|
||||
title: Text(l10n.rubyTitle),
|
||||
content: TextField(
|
||||
maxLength: TextLimits.secondary,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _reading,
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import 'package:halkyon_learn_flutter/src/core/dependencies/dependencies_scope.d
|
|||
import 'package:halkyon_learn_flutter/src/core/editor/atomic_block.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/editor/editor_blocks.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/video/youtube_videos.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
|
|
@ -279,6 +280,8 @@ class _VideoDialogState() extends State<_VideoDialog> {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextField(
|
||||
maxLength: TextLimits.address,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _link,
|
||||
autofocus: true,
|
||||
keyboardType: TextInputType.url,
|
||||
|
|
@ -293,6 +296,8 @@ class _VideoDialogState() extends State<_VideoDialog> {
|
|||
),
|
||||
const SizedBox(height: 16),
|
||||
TextField(
|
||||
maxLength: TextLimits.title,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _caption,
|
||||
decoration: InputDecoration(
|
||||
labelText: l10n.youtubeCaption,
|
||||
|
|
|
|||
68
halkyon_learn_flutter/lib/src/core/widget/text_limits.dart
Normal file
68
halkyon_learn_flutter/lib/src/core/widget/text_limits.dart
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// How long what people type into the app's fields may be, by what it is
|
||||
/// (decided 2026-10-11): enough for any real one, short enough to show
|
||||
/// without breaking a row. A field stops there ([TextField.maxLength]) and
|
||||
/// counts only near the end ([nearLimitCounter]). Text can still be longer
|
||||
/// where it came from elsewhere (an older app, an import, another person's
|
||||
/// release), so every place that shows it cuts it short as well. The server
|
||||
/// keeps its own limits where it checks what is sent (a public profile, a
|
||||
/// release); the app's fields for those take the server's.
|
||||
abstract final class TextLimits() {
|
||||
/// A name shown in a menu, on a chip or a button: a Pomodoro profile, a
|
||||
/// tag, a study button's label.
|
||||
static const name = 40;
|
||||
|
||||
/// A short line beside a title or above a word: a studyset's or a path's
|
||||
/// secondary title, a reading set above characters.
|
||||
static const secondary = 60;
|
||||
|
||||
/// The title of something holding content: a studyset, a note, a path, a
|
||||
/// step, a PDF, a callout, a video's caption; who holds a licence.
|
||||
static const title = 120;
|
||||
|
||||
/// One answer or item: a meaning, a reading, a gloss, an option, a
|
||||
/// category, a gap, an answer typed while studying.
|
||||
static const phrase = 200;
|
||||
|
||||
/// What is searched for.
|
||||
static const search = 200;
|
||||
|
||||
/// A part of a citation: its authors, title, publisher, and so on.
|
||||
static const reference = 500;
|
||||
|
||||
/// A message to someone: a report's note, a reply, a question asked.
|
||||
static const message = 2000;
|
||||
|
||||
/// A web address: a link, a search engine's, an instance's.
|
||||
static const address = 2000;
|
||||
|
||||
/// A longer text typed as one field: a passage with gaps, a formula.
|
||||
static const passage = 5000;
|
||||
|
||||
/// The share of a limit from which a field counts its characters.
|
||||
static const countFrom = 0.8;
|
||||
}
|
||||
|
||||
/// A text field's counter ([TextField.buildCounter]) that shows only once
|
||||
/// the text is near its limit, "38 / 40", in the error colour at the limit:
|
||||
/// a counter under every title would only be noise.
|
||||
Widget? nearLimitCounter(
|
||||
BuildContext context, {
|
||||
required int currentLength,
|
||||
required int? maxLength,
|
||||
required bool isFocused,
|
||||
}) {
|
||||
if (maxLength == null || currentLength < maxLength * TextLimits.countFrom) {
|
||||
return null;
|
||||
}
|
||||
final theme = Theme.of(context);
|
||||
return Text(
|
||||
'$currentLength / $maxLength',
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: currentLength >= maxLength
|
||||
? theme.colorScheme.error
|
||||
: theme.colorScheme.onSurfaceVariant,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/dependencies/dependencies_scope.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/device_settings/bloc/device_settings_bloc.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/device_settings/model/device_settings.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/assistant/model/assistant_topic.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/assistant/model/search_engine.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
|
|
@ -167,6 +168,8 @@ class _AssistantFieldState() extends State<AssistantField> {
|
|||
_TargetSwitch(target: target, onSwitch: () => _switch(target)),
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLength: TextLimits.message,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _question,
|
||||
autofocus: widget.autofocus,
|
||||
minLines: 1,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import 'package:halkyon_learn_flutter/src/core/device_settings/model/device_sett
|
|||
import 'package:halkyon_learn_flutter/src/core/router/route_paths.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/adaptive_sheet.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/section_card.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/assistant/model/search_engine.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
|
@ -160,6 +161,8 @@ class _EngineSheetState() extends State<_EngineSheet> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 0),
|
||||
child: TextField(
|
||||
maxLength: TextLimits.address,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _url,
|
||||
autofocus: true,
|
||||
keyboardType: TextInputType.url,
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import 'package:halkyon_learn_flutter/src/core/router/route_paths.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/theme/theme_extras.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/app_loading_indicator.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/confirm_dialog.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/top_gradient.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/undo_snack_bar.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/bloc/card_browser_bloc.dart';
|
||||
|
|
@ -617,6 +618,8 @@ class const _SearchRow({
|
|||
child: ListenableBuilder(
|
||||
listenable: controller,
|
||||
builder: (context, _) => TextField(
|
||||
maxLength: TextLimits.search,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
textInputAction: TextInputAction.search,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
|
@ -71,6 +72,8 @@ class _CharacterFieldsState() extends State<CharacterFields> {
|
|||
Text(label, style: labelStyle),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
maxLength: TextLimits.phrase,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: controller,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
|
|
@ -93,6 +96,8 @@ class _CharacterFieldsState() extends State<CharacterFields> {
|
|||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLength: TextLimits.phrase,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: meaning,
|
||||
decoration: InputDecoration(
|
||||
hintText: i == 0
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
|
@ -98,6 +99,8 @@ class _MatchingFieldsState() extends State<MatchingFields> {
|
|||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLength: TextLimits.phrase,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: target,
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.matchingCategory(t + 1),
|
||||
|
|
@ -151,6 +154,8 @@ class _MatchingFieldsState() extends State<MatchingFields> {
|
|||
Expanded(
|
||||
flex: 2,
|
||||
child: TextField(
|
||||
maxLength: TextLimits.phrase,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: item,
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.matchingItem(i + 1),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/model/jmdict_tags.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
|
|
@ -66,6 +67,8 @@ class _VocabularyFieldsState() extends State<VocabularyFields> {
|
|||
Text(l10n.vocabularyReading, style: labelStyle),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
maxLength: TextLimits.phrase,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _reading,
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.vocabularyReadingHint,
|
||||
|
|
@ -90,6 +93,8 @@ class _VocabularyFieldsState() extends State<VocabularyFields> {
|
|||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLength: TextLimits.phrase,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: meaning,
|
||||
decoration: InputDecoration(
|
||||
hintText: i == 0
|
||||
|
|
@ -222,6 +227,8 @@ class _SenseFieldsState() extends State<_SenseFields> {
|
|||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLength: TextLimits.phrase,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: gloss,
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.vocabularyGlossHint,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:clock/clock.dart';
|
||||
import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/adaptive_sheet.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
|
@ -100,6 +101,8 @@ class _ReportSheetState() extends State<_ReportSheet> {
|
|||
),
|
||||
const SizedBox(height: 16),
|
||||
TextField(
|
||||
maxLength: TextLimits.message,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _note,
|
||||
minLines: 2,
|
||||
maxLines: 4,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/dependencies/dependencies_scope.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/adaptive_sheet.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/app_loading_indicator.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/dictionary/model/dictionary.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/dictionary/widget/dictionary_word_tile.dart';
|
||||
|
|
@ -94,6 +95,8 @@ class _LookUpState() extends State<_LookUp> {
|
|||
children: [
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
maxLength: TextLimits.search,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _query,
|
||||
autofocus: widget.query.isEmpty,
|
||||
textInputAction: TextInputAction.search,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import 'package:halkyon_learn_flutter/src/core/dependencies/dependencies_scope.d
|
|||
import 'package:halkyon_learn_flutter/src/core/dependencies/person_scope.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/layout/readable_width.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/app_loading_indicator.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/top_gradient.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/dictionary/bloc/dictionary_bloc.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/dictionary/data/dictionary_adder.dart';
|
||||
|
|
@ -222,6 +223,8 @@ class _DictionaryViewState()
|
|||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
|
||||
child: TextField(
|
||||
maxLength: TextLimits.search,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _query,
|
||||
autofocus: true,
|
||||
textInputAction: TextInputAction.search,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/content/published_ref.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/dependencies/person_scope.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/adaptive_sheet.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/auth/bloc/session_bloc.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/model/card_content.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/feedback/bloc/inbox_count_bloc.dart';
|
||||
|
|
@ -150,6 +151,8 @@ class _MessageSheetState() extends State<_MessageSheet> {
|
|||
const SizedBox(height: 16),
|
||||
],
|
||||
TextField(
|
||||
maxLength: TextLimits.message,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _text,
|
||||
minLines: 3,
|
||||
maxLines: 8,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:halkyon_learn_flutter/src/core/dependencies/person_scope.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/widget/adaptive_sheet.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/app_loading_indicator.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/confirm_dialog.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/card/widget/report_sheet.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/feedback/bloc/feedback_list_bloc.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/feedback/model/feedback.dart';
|
||||
|
|
@ -232,6 +233,8 @@ class _ThreadSheetState() extends State<_ThreadSheet> {
|
|||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
maxLength: TextLimits.message,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _reply,
|
||||
minLines: 1,
|
||||
maxLines: 4,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:halkyon_learn_flutter/l10n/app_localizations.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/instance/instance.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/instance/instance_checker.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:material_ui/material_ui.dart';
|
||||
|
||||
/// Choosing an instance, as Mastodon's apps do: its address typed, checked
|
||||
|
|
@ -92,6 +93,8 @@ class _InstanceStepState() extends State<InstanceStep> {
|
|||
const SizedBox(height: 24),
|
||||
],
|
||||
TextField(
|
||||
maxLength: TextLimits.address,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _address,
|
||||
enabled: !_checking,
|
||||
autocorrect: false,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import 'package:halkyon_learn_flutter/src/core/layout/readable_width.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/router/route_paths.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/app_loading_indicator.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/section_card.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/top_gradient.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/undo_snack_bar.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/learning_path/bloc/path_editor_bloc.dart';
|
||||
|
|
@ -119,6 +120,8 @@ class _PathEditorScreenState() extends State<PathEditorScreen> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 8, 16, 0),
|
||||
child: TextField(
|
||||
maxLength: TextLimits.title,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _title,
|
||||
style: theme.textTheme.headlineSmall,
|
||||
decoration: InputDecoration(
|
||||
|
|
@ -134,6 +137,8 @@ class _PathEditorScreenState() extends State<PathEditorScreen> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
|
||||
child: TextField(
|
||||
maxLength: TextLimits.secondary,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _secondary,
|
||||
style: theme.textTheme.titleSmall?.copyWith(
|
||||
color: theme.colorScheme.onSurfaceVariant,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import 'package:halkyon_learn_flutter/src/core/widget/empty_list_message.dart';
|
|||
import 'package:halkyon_learn_flutter/src/core/widget/lift_while_dragged.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/reorder_grip.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/sliver_centered.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/text_limits.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/title_with_kicker.dart';
|
||||
import 'package:halkyon_learn_flutter/src/core/widget/undo_snack_bar.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/learning_path/bloc/path_list_bloc.dart';
|
||||
|
|
@ -267,6 +268,8 @@ class _NewPathSheetState() extends State<_NewPathSheet> {
|
|||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
TextField(
|
||||
maxLength: TextLimits.title,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _title,
|
||||
autofocus: true,
|
||||
decoration: InputDecoration(labelText: l10n.pathTitleLabel),
|
||||
|
|
@ -275,6 +278,8 @@ class _NewPathSheetState() extends State<_NewPathSheet> {
|
|||
),
|
||||
const SizedBox(height: 12),
|
||||
TextField(
|
||||
maxLength: TextLimits.secondary,
|
||||
buildCounter: nearLimitCounter,
|
||||
controller: _secondary,
|
||||
decoration: InputDecoration(
|
||||
labelText: l10n.pathSecondaryTitleLabel,
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue