Skip to content

Commit

Permalink
fix: character limit
Browse files Browse the repository at this point in the history
  • Loading branch information
Arenukvern committed Feb 12, 2024
1 parent 1087a54 commit f041581
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 60 deletions.
2 changes: 1 addition & 1 deletion lib/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ Future<void> bootstrap({
final GlobalServicesInitializer initializer = GlobalServicesInitializerImpl(
firebaseOptions: firebaseOptions,
);
unawaited(initializer.onLoad());
await runZonedGuarded(
() async {
WidgetsFlutterBinding.ensureInitialized();
unawaited(initializer.onLoad());
runApp(const LastAnswerApp());
},
initializer.analyticsService.recordError,
Expand Down
2 changes: 1 addition & 1 deletion lib/note/note_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class NoteViewBody extends StatelessWidget {
filled: false,
hasBorder: false,
contentPadding: const EdgeInsets.only(left: 24),
limit: int.tryParse(bloc.characterLimitController.value),
limit: int.tryParse(bloc.characterLimitController.limit),
focusNode: bloc.focusNode,
endlessLines: true,
focusOnInit: bloc.dto.initialNote.note.isEmpty,
Expand Down
2 changes: 1 addition & 1 deletion lib/note/note_view_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class NoteViewBloc extends ValueNotifier<ProjectModelNote> {
void _onChanged() {
final updatedNote = value.copyWith(
note: noteController.text,
charactersLimit: int.tryParse(characterLimitController.value) ?? 0,
charactersLimit: int.tryParse(characterLimitController.limit) ?? 0,
);
setValue(updatedNote);
dto.openedProjectNotifier.updateProject(updatedNote);
Expand Down
33 changes: 15 additions & 18 deletions lib/settings/features/characters_limit.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,30 +12,20 @@ class CharactersLimitSetting extends HookWidget {

@override
Widget build(final BuildContext context) {
final theme = Theme.of(context);
final theme = context.theme;
final dark = theme.brightness == Brightness.dark;
useListenable(controller);
Widget otherButton;

// TODO(arenukvern): refactor to separate widget
if (controller.noLimitIsSet) {
otherButton = Padding(
padding: const EdgeInsets.only(right: 8),
child: HoverableButton(
onPressed: () => controller.setLimit(
0,
zeroEqualNull: false,
),
child: Text(context.l10n.charactersUnlimited),
),
);
} else {
if (controller.isEditing) {
otherButton = Row(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(width: 12),
const Gap(12),
UiTextField(
value: controller.value,
value: controller.limit,
focusNode: controller.focusNode,
onChanged: controller.onLimitChanged,
keyboardType: TextInputType.number,
autocorrect: false,
Expand All @@ -48,17 +38,24 @@ class CharactersLimitSetting extends HookWidget {
constraints: const BoxConstraints(maxWidth: 60),
),
),
const SizedBox(width: 2),
const Gap(2),
HoverableButton(
onPressed:
controller.value.isEmpty ? null : controller.onClearLimit,
onPressed: controller.isEditing ? controller.onClearLimit : null,
child: const Icon(
CupertinoIcons.clear,
size: 14,
),
),
],
);
} else {
otherButton = Padding(
padding: const EdgeInsets.only(right: 8),
child: HoverableButton(
onPressed: () => controller.setIsEditing(true),
child: Text(context.l10n.charactersUnlimited),
),
);
}
// TODO(arenukvern): refactor to separate widget

Expand Down
100 changes: 62 additions & 38 deletions lib/settings/features/characters_limit_state.dart
Original file line number Diff line number Diff line change
@@ -1,108 +1,132 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:lastanswer/common_imports.dart';

part 'characters_limit_state.freezed.dart';

class CharactersLimitControllerDto {
CharactersLimitControllerDto({
required final BuildContext context,
}) : userNotifier = context.read<UserNotifier>();
final UserNotifier userNotifier;
}

class CharactersLimitController extends ValueNotifier<String> {
@freezed
class CharacterLimitState with _$CharacterLimitState {
const factory CharacterLimitState({
@Default('') final String value,
@Default(false) final bool isEditing,
}) = _CharacterLimitState;
factory CharacterLimitState.fromDto({
required final CharactersLimitControllerDto dto,
final int? noteCharactersLimit,
}) {
final initialLimit = _getInitialLimit(
userNotifier: dto.userNotifier,
noteCharactersLimit: noteCharactersLimit,
);
return CharacterLimitState(
isEditing: initialLimit.isNotEmpty,
value: initialLimit,
);
}
static String _getInitialLimit({
required final UserNotifier userNotifier,
final int? noteCharactersLimit,
}) {
final limit =
noteCharactersLimit ?? userNotifier.settings.charactersLimitForNewNotes;

return limit <= 0 ? '' : '$limit';
}
}

class CharactersLimitController extends ValueNotifier<CharacterLimitState> {
CharactersLimitController.fromNote({
required final int noteCharactersLimit,
required this.dto,
}) : super(
_getInitialLimit(
CharacterLimitState.fromDto(
noteCharactersLimit: noteCharactersLimit,
userNotifier: dto.userNotifier,
dto: dto,
),
);
CharactersLimitController.fromSettings({
required this.dto,
}) : super(_getInitialLimit(userNotifier: dto.userNotifier));
}) : super(CharacterLimitState.fromDto(dto: dto));
final CharactersLimitControllerDto dto;

static String _getInitialLimit({
required final UserNotifier userNotifier,
final int? noteCharactersLimit,
}) {
int limit;

if (noteCharactersLimit != null) {
limit = noteCharactersLimit;
} else {
limit = userNotifier.settings.charactersLimitForNewNotes;
}

return limit == 0 ? '' : '$limit';
final focusNode = FocusNode();
@override
void dispose() {
focusNode.dispose();
super.dispose();
}

void onLimitChanged(final String? value) {
final limit = int.tryParse(value ?? '') ?? 0;
setLimit(limit, zeroEqualNull: false);
final limit = int.tryParse(value ?? '');
setLimit(limit);
}

void setLimit(
final int newLimit, {
final bool zeroEqualNull = true,
}) {
final str = '$newLimit';
if (zeroEqualNull && newLimit == 0) {
setValue('');
} else {
setValue(str);
}
// ignore: avoid_positional_boolean_parameters
void setIsEditing(final bool isEditing) {
setValue(value.copyWith(isEditing: isEditing));
if (isEditing) focusNode.requestFocus();
}

void setLimit(final int? newLimit, {final bool isEditing = true}) {
final str = newLimit == null || newLimit <= 0 ? '' : '$newLimit';
setValue(value.copyWith(value: str, isEditing: isEditing));
}

bool get noLimitIsSet => value.isEmpty;
bool get isEditing => value.isEditing;
String get limit => value.value;

void onClearLimit() {
setLimit(0);
setLimit(null, isEditing: false);
}

static const int instagramLimit = 2200;
static const String instagramLimitStr = '$instagramLimit';
bool get isInstagramLimit => value == instagramLimitStr;
bool get isInstagramLimit => limit == instagramLimitStr;
void onSetInstagramLimit() {
final newLimit = isInstagramLimit ? 0 : instagramLimit;
setLimit(newLimit);
}

static const int twitterLimit = 280;
static const String twitterLimitStr = '$twitterLimit';
bool get isTwitterLimit => value == twitterLimitStr;
bool get isTwitterLimit => limit == twitterLimitStr;
void onSetTwitterLimit() {
final newLimit = isTwitterLimit ? 0 : twitterLimit;
setLimit(newLimit);
}

static const int vkLimit = 4096;
static const String vkLimitStr = '$vkLimit';
bool get isVkLimit => value == vkLimitStr;
bool get isVkLimit => limit == vkLimitStr;
void onSetVkLimit() {
final newLimit = isVkLimit ? 0 : vkLimit;
setLimit(newLimit);
}

static const int facebookLimit = 63206;
static const String facebookLimitStr = '$facebookLimit';
bool get isFacebookLimit => value == facebookLimitStr;
bool get isFacebookLimit => limit == facebookLimitStr;
void onSetFacebookLimit() {
final newLimit = isFacebookLimit ? 0 : facebookLimit;
setLimit(newLimit);
}

static const int discordLimit = 2000;
static const String discordLimitStr = '$discordLimit';
bool get isDiscordLimit => value == discordLimitStr;
bool get isDiscordLimit => limit == discordLimitStr;
void onSetDiscordLimit() {
final newLimit = isDiscordLimit ? 0 : discordLimit;
setLimit(newLimit);
}

static const int telegramLimit = 2200;
static const String telegramLimitStr = '$telegramLimit';
bool get isTelegramLimit => value == telegramLimitStr;
bool get isTelegramLimit => limit == telegramLimitStr;
void onSetTelegramLimit() {
final newLimit = isTelegramLimit ? 0 : telegramLimit;
setLimit(newLimit);
Expand Down
Loading

0 comments on commit f041581

Please sign in to comment.