improving text_layer editor

This commit is contained in:
otsmr 2025-06-06 09:40:51 +02:00
parent 0bd810f82c
commit 41b67090f3
6 changed files with 60 additions and 23 deletions

View file

@ -3,6 +3,7 @@ import 'package:flutter/services.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/database/twonly_database.dart'; import 'package:twonly/src/database/twonly_database.dart';
import 'package:twonly/src/providers/image_editor.provider.dart';
import 'package:twonly/src/services/api/media_received.dart'; import 'package:twonly/src/services/api/media_received.dart';
import 'package:twonly/src/services/api/media_send.dart'; import 'package:twonly/src/services/api/media_send.dart';
import 'package:twonly/src/services/api.service.dart'; import 'package:twonly/src/services/api.service.dart';
@ -52,6 +53,7 @@ void main() async {
providers: [ providers: [
ChangeNotifierProvider(create: (_) => settingsController), ChangeNotifierProvider(create: (_) => settingsController),
ChangeNotifierProvider(create: (_) => CustomChangeProvider()), ChangeNotifierProvider(create: (_) => CustomChangeProvider()),
ChangeNotifierProvider(create: (_) => ImageEditorProvider()),
], ],
child: App(), child: App(),
), ),

View file

@ -0,0 +1,11 @@
import 'package:flutter/foundation.dart';
class ImageEditorProvider with ChangeNotifier, DiagnosticableTreeMixin {
bool _someTextViewIsAlreadyEditing = false;
bool get someTextViewIsAlreadyEditing => _someTextViewIsAlreadyEditing;
Future<void> updateSomeTextViewIsAlreadyEditing(bool update) async {
_someTextViewIsAlreadyEditing = update;
notifyListeners();
}
}

View file

@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
import 'package:twonly/src/providers/image_editor.provider.dart';
import 'package:twonly/src/views/camera/image_editor/action_button.dart'; import 'package:twonly/src/views/camera/image_editor/action_button.dart';
import 'package:twonly/src/views/camera/image_editor/data/layer.dart'; import 'package:twonly/src/views/camera/image_editor/data/layer.dart';
@ -65,6 +67,9 @@ class _TextViewState extends State<TextLayer> {
setState(() { setState(() {
widget.layerData.isDeleted = textController.text == ""; widget.layerData.isDeleted = textController.text == "";
widget.layerData.isEditing = false; widget.layerData.isEditing = false;
context
.read<ImageEditorProvider>()
.updateSomeTextViewIsAlreadyEditing(false);
widget.layerData.text = textController.text; widget.layerData.text = textController.text;
}); });
}, },
@ -75,6 +80,9 @@ class _TextViewState extends State<TextLayer> {
setState(() { setState(() {
widget.layerData.isDeleted = textController.text == ""; widget.layerData.isDeleted = textController.text == "";
widget.layerData.isEditing = false; widget.layerData.isEditing = false;
context
.read<ImageEditorProvider>()
.updateSomeTextViewIsAlreadyEditing(false);
}); });
} }
}); });
@ -96,6 +104,7 @@ class _TextViewState extends State<TextLayer> {
), ),
); );
} }
return Stack( return Stack(
key: _widgetKey, key: _widgetKey,
children: [ children: [
@ -110,15 +119,25 @@ class _TextViewState extends State<TextLayer> {
}); });
}, },
onScaleEnd: (d) { onScaleEnd: (d) {
if (deleteLayer) widget.layerData.isDeleted = true; if (deleteLayer) {
widget.layerData.isDeleted = true;
textController.text = "";
}
elementIsScaled = false; elementIsScaled = false;
setState(() {}); setState(() {});
}, },
onTap: () { onTap: (context
setState(() { .watch<ImageEditorProvider>()
widget.layerData.isEditing = true; .someTextViewIsAlreadyEditing)
}); ? null
}, : () {
setState(() {
context
.read<ImageEditorProvider>()
.updateSomeTextViewIsAlreadyEditing(true);
widget.layerData.isEditing = true;
});
},
onScaleUpdate: (detail) { onScaleUpdate: (detail) {
if (detail.pointerCount == 1) { if (detail.pointerCount == 1) {
widget.layerData.offset = Offset( widget.layerData.offset = Offset(

View file

@ -53,7 +53,7 @@ class LayersViewer extends StatelessWidget {
}), }),
...layers.whereType<TextLayerData>().map((layerItem) { ...layers.whereType<TextLayerData>().map((layerItem) {
return TextLayer( return TextLayer(
key: GlobalKey(), // key: GlobalKey(),
layerData: layerItem, layerData: layerItem,
onUpdate: onUpdate, onUpdate: onUpdate,
); );

View file

@ -56,6 +56,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
String? sendNextMediaToUserName; String? sendNextMediaToUserName;
double tabDownPosition = 0; double tabDownPosition = 0;
bool sendingOrLoadingImage = true; bool sendingOrLoadingImage = true;
bool loadingImage = true;
bool isDisposed = false; bool isDisposed = false;
HashSet<int> selectedUserIds = HashSet(); HashSet<int> selectedUserIds = HashSet();
double widthRatio = 1, heightRatio = 1, pixelRatio = 1; double widthRatio = 1, heightRatio = 1, pixelRatio = 1;
@ -78,6 +79,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
} else if (widget.videoFilePath != null) { } else if (widget.videoFilePath != null) {
setState(() { setState(() {
sendingOrLoadingImage = false; sendingOrLoadingImage = false;
loadingImage = false;
}); });
videoController = VideoPlayerController.file(widget.videoFilePath!); videoController = VideoPlayerController.file(widget.videoFilePath!);
videoController?.setLooping(true); videoController?.setLooping(true);
@ -381,6 +383,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
); );
setState(() { setState(() {
sendingOrLoadingImage = false; sendingOrLoadingImage = false;
loadingImage = false;
}); });
} }
@ -535,11 +538,12 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
SaveToGalleryButton( SaveToGalleryButton(
getMergedImage: getMergedImage, getMergedImage: getMergedImage,
mediaUploadId: mediaUploadId, mediaUploadId: mediaUploadId,
videoFilePath: widget.videoFilePath, videoFilePath: widget.videoFilePath,
sendNextMediaToUserName: sendNextMediaToUserName, sendNextMediaToUserName: sendNextMediaToUserName,
isLoading: sendingOrLoadingImage), isLoading: loadingImage,
),
if (sendNextMediaToUserName != null) SizedBox(width: 10), if (sendNextMediaToUserName != null) SizedBox(width: 10),
if (sendNextMediaToUserName != null) if (sendNextMediaToUserName != null)
OutlinedButton( OutlinedButton(

View file

@ -17,17 +17,18 @@ import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/settings/subscription/subscription.view.dart'; import 'package:twonly/src/views/settings/subscription/subscription.view.dart';
class ShareImageView extends StatefulWidget { class ShareImageView extends StatefulWidget {
const ShareImageView( const ShareImageView({
{super.key, super.key,
required this.imageBytesFuture, required this.imageBytesFuture,
required this.isRealTwonly, required this.isRealTwonly,
required this.mirrorVideo, required this.mirrorVideo,
required this.maxShowTime, required this.maxShowTime,
required this.selectedUserIds, required this.selectedUserIds,
required this.updateStatus, required this.updateStatus,
required this.videoUploadHandler, required this.videoUploadHandler,
required this.mediaUploadId, required this.mediaUploadId,
this.enableVideoAudio}); this.enableVideoAudio,
});
final Future<Uint8List?> imageBytesFuture; final Future<Uint8List?> imageBytesFuture;
final bool isRealTwonly; final bool isRealTwonly;
final bool mirrorVideo; final bool mirrorVideo;