From 5165396c27d12086789a6c9235cb7b70131f2f1d Mon Sep 17 00:00:00 2001 From: Dane Madsen Date: Thu, 25 Apr 2024 16:48:16 +1000 Subject: [PATCH] Fixes to CharacterBrowserTile (#515) * fix issue with character card browser * fix same issue * work on character browser tiles * fix browser tile * fix character browser * long press character card --- lib/providers/character.dart | 32 ++-- .../character/character_browser_page.dart | 9 +- .../character_customization_page.dart | 26 ++-- .../widgets/tiles/character_browser_tile.dart | 141 ++++++++++-------- 4 files changed, 124 insertions(+), 84 deletions(-) diff --git a/lib/providers/character.dart b/lib/providers/character.dart index a44c02d9..c62f01d5 100644 --- a/lib/providers/character.dart +++ b/lib/providers/character.dart @@ -275,19 +275,25 @@ class Character extends ChangeNotifier { } String get hash { - List hashList = [ - _name, - _description, - _personality, - _scenario, - _system, - _useGreeting.toString(), - _greetings.join(), - _useExamples.toString(), - _examples.join(), - ]; - - final bytes = utf8.encode(hashList.join()); + Uint8List bytes; + + if(_profile != null) { + bytes = _profile!.readAsBytesSync(); + } else { + List hashList = [ + _name, + _description, + _personality, + _scenario, + _system, + _useGreeting.toString(), + _greetings.join(), + _useExamples.toString(), + _examples.join(), + ]; + + bytes = utf8.encode(hashList.join()); + } return sha256.convert(bytes).toString(); } diff --git a/lib/ui/mobile/pages/character/character_browser_page.dart b/lib/ui/mobile/pages/character/character_browser_page.dart index 12a24451..593683c6 100644 --- a/lib/ui/mobile/pages/character/character_browser_page.dart +++ b/lib/ui/mobile/pages/character/character_browser_page.dart @@ -26,12 +26,17 @@ class _CharacterBrowserPageState extends State { Future _loadCharacters() async { final prefs = await SharedPreferences.getInstance(); - final String charactersJson = prefs.getString("characters") ?? '[]'; + + final String? charactersJson = prefs.getString("characters"); + if (charactersJson == null) { + return; + } + final List charactersList = json.decode(charactersJson); setState(() { characters.clear(); - for (var characterMap in charactersList) { + for (final characterMap in charactersList) { characters.add(Character.fromMap(characterMap)); } }); diff --git a/lib/ui/mobile/pages/character/character_customization_page.dart b/lib/ui/mobile/pages/character/character_customization_page.dart index 30392e22..25e76ced 100644 --- a/lib/ui/mobile/pages/character/character_customization_page.dart +++ b/lib/ui/mobile/pages/character/character_customization_page.dart @@ -34,7 +34,12 @@ class _CharacterCustomizationPageState extends State final prefs = await SharedPreferences.getInstance(); final characterString = prefs.getString("last_character"); - final character = Character.fromMap(json.decode(characterString ?? "{}")); + + if (characterString == null) { + return; + } + + final character = Character.fromMap(json.decode(characterString)); final String charactersJson = prefs.getString("characters") ?? '[]'; final List charactersList = json.decode(charactersJson); @@ -80,6 +85,10 @@ class _CharacterCustomizationPageState extends State appBar: const GenericAppBar(title: "Character Customization"), body: Consumer( builder: (context, character, child) { + SharedPreferences.getInstance().then((prefs) { + prefs.setString("last_character", json.encode(character.toMap())); + }); + if (regenerate) { nameController = TextEditingController(text: character.name); descriptionController = TextEditingController(text: character.description); @@ -103,10 +112,6 @@ class _CharacterCustomizationPageState extends State regenerate = false; } - SharedPreferences.getInstance().then((prefs) { - prefs.setString("last_character", json.encode(character.toMap())); - }); - return SessionBusyOverlay( child: SingleChildScrollView( child: Column( @@ -205,11 +210,14 @@ class _CharacterCustomizationPageState extends State children: [ FilledButton( onPressed: () { + Navigator.of(context).pop(); Navigator.push( - context, - MaterialPageRoute( - builder: (context) => - const CharacterBrowserPage())); + context, + MaterialPageRoute( + builder: (context) => + const CharacterBrowserPage() + ) + ); }, child: Text( "Switch Character", diff --git a/lib/ui/mobile/widgets/tiles/character_browser_tile.dart b/lib/ui/mobile/widgets/tiles/character_browser_tile.dart index f87b64c1..9ff57de6 100644 --- a/lib/ui/mobile/widgets/tiles/character_browser_tile.dart +++ b/lib/ui/mobile/widgets/tiles/character_browser_tile.dart @@ -1,8 +1,10 @@ +import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:maid/providers/character.dart'; import 'package:maid/static/logger.dart'; +import 'package:maid/ui/mobile/pages/character/character_customization_page.dart'; import 'package:provider/provider.dart'; class CharacterBrowserTile extends StatefulWidget { @@ -17,78 +19,97 @@ class CharacterBrowserTile extends StatefulWidget { } class _CharacterBrowserTileState extends State { + Timer? longPressTimer; + @override Widget build(BuildContext context) { - return GestureDetector( - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: FutureBuilder( - future: widget.character.profile, - builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.done) { - if (snapshot.hasError) { - return const Icon(Icons.error); + return ClipRRect( + borderRadius: BorderRadius.circular(10), + child: Stack( + fit: StackFit.expand, + children: [ + FutureBuilder( + future: widget.character.profile, + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + if (snapshot.hasError) { + return const Icon(Icons.error); + } else { + return Image.file( + snapshot.data!, + fit: BoxFit.cover, + ); + } } else { - return Stack( - fit: StackFit.expand, + return const CircularProgressIndicator(); + } + } + ), + Material( + color: Colors.transparent, + child: InkWell( + hoverColor: Colors.black.withOpacity(0.1), + highlightColor: Colors.black.withOpacity(0.2), + splashColor: Colors.black.withOpacity(0.2), + onTapDown: onTapDown, + onTapUp: onTapUp, + onSecondaryTapUp: (details) => showContextMenu(details.globalPosition), + child: Container( + padding: const EdgeInsets.all(8), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomCenter, + end: Alignment.center, + colors: [Colors.black, Colors.transparent], + ), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Image.file( - snapshot.data!, - fit: BoxFit.cover, + Text( + widget.character.name, + style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold), ), - Align( - alignment: Alignment.bottomCenter, - child: Container( - padding: const EdgeInsets.all(8), - decoration: BoxDecoration( - gradient: LinearGradient( - begin: Alignment.bottomCenter, - end: Alignment.topCenter, - colors: [Colors.black.withOpacity(0.8), Colors.transparent], - ), - ), - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - widget.character.name, - style: const TextStyle(color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold), - ), - Text( - widget.character.description, - maxLines: 3, - overflow: TextOverflow.ellipsis, - style: const TextStyle(color: Colors.white), - ), - ], - ), - ), + Text( + widget.character.description, + maxLines: 3, + overflow: TextOverflow.ellipsis, + style: const TextStyle(color: Colors.white), ), ], - ); - } - } else { - return const CircularProgressIndicator(); - } - } - ) - ), - onTap: () { - context.read().from(widget.character); - }, - onSecondaryTapUp: (details) => _onSecondaryTapUp(details, context), - onLongPressStart: (details) => _onLongPressStart(details, context), + ), + ) + ) + ) + ], + ) ); } - void _onSecondaryTapUp(TapUpDetails details, BuildContext context) => - _showContextMenu(details.globalPosition, context); + void onTapDown(TapDownDetails details) { + longPressTimer = Timer(const Duration(seconds: 1), () { + showContextMenu(details.globalPosition); + }); + } - void _onLongPressStart(LongPressStartDetails details, BuildContext context) => - _showContextMenu(details.globalPosition, context); + void onTapUp(TapUpDetails details) { + if (longPressTimer?.isActive ?? false) { + longPressTimer?.cancel(); + context.read().from(widget.character); + Navigator.of(context).pop(); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => + const CharacterCustomizationPage() + ) + ); + } + } - void _showContextMenu(Offset position, BuildContext context) { + void showContextMenu(Offset position) { final RenderBox overlay = Overlay.of(context).context.findRenderObject() as RenderBox; final TextEditingController controller =