feat: Enhance emote experience
This commit is contained in:
parent
090795fa77
commit
cafd639c24
|
@ -1,4 +1,9 @@
|
||||||
# Version 0.19.0 - 2020-??-??
|
# Version 0.20.0 - 2020-??-??
|
||||||
|
### Features
|
||||||
|
- Add ability to enable / disable emotes globally
|
||||||
|
- Add ability to manage emote packs with different state keys
|
||||||
|
|
||||||
|
# Version 0.19.0 - 2020-09-21
|
||||||
### Features
|
### Features
|
||||||
- Implemented ignore list
|
- Implemented ignore list
|
||||||
- Jump to events in timeline: When tapping on a reply and when tapping a matrix.to link
|
- Jump to events in timeline: When tapping on a reply and when tapping a matrix.to link
|
||||||
|
|
|
@ -237,22 +237,10 @@ class InputBar extends StatelessWidget {
|
||||||
}
|
}
|
||||||
if (insertText.isNotEmpty && startText.isNotEmpty) {
|
if (insertText.isNotEmpty && startText.isNotEmpty) {
|
||||||
controller.text = startText + afterText;
|
controller.text = startText + afterText;
|
||||||
if (startText == insertText) {
|
controller.selection = TextSelection(
|
||||||
// stupid fix for now
|
baseOffset: startText.length,
|
||||||
FocusScope.of(context).requestFocus(FocusNode());
|
extentOffset: startText.length,
|
||||||
Future.delayed(Duration(milliseconds: 1)).then((res) {
|
);
|
||||||
focusNode.requestFocus();
|
|
||||||
controller.selection = TextSelection(
|
|
||||||
baseOffset: startText.length,
|
|
||||||
extentOffset: startText.length,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
controller.selection = TextSelection(
|
|
||||||
baseOffset: startText.length,
|
|
||||||
extentOffset: startText.length,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -529,11 +529,21 @@
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"emotePacks": "Emote packs for room",
|
||||||
|
"@emotePacks": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"emptyChat": "Empty chat",
|
"emptyChat": "Empty chat",
|
||||||
"@emptyChat": {
|
"@emptyChat": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
|
"enableEmotesGlobally": "Enable emote pack globally",
|
||||||
|
"@enableEmotesGlobally": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
"enableEncryptionWarning": "You won't be able to disable the encryption anymore. Are you sure?",
|
"enableEncryptionWarning": "You won't be able to disable the encryption anymore. Are you sure?",
|
||||||
"@enableEncryptionWarning": {
|
"@enableEncryptionWarning": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
|
|
|
@ -19,6 +19,7 @@ import 'package:matrix_link_text/link_text.dart';
|
||||||
import 'package:memoryfilepicker/memoryfilepicker.dart';
|
import 'package:memoryfilepicker/memoryfilepicker.dart';
|
||||||
|
|
||||||
import './settings_emotes.dart';
|
import './settings_emotes.dart';
|
||||||
|
import './settings_multiple_emotes.dart';
|
||||||
import '../utils/url_launcher.dart';
|
import '../utils/url_launcher.dart';
|
||||||
|
|
||||||
class ChatDetails extends StatefulWidget {
|
class ChatDetails extends StatefulWidget {
|
||||||
|
@ -285,13 +286,31 @@ class _ChatDetailsState extends State<ChatDetails> {
|
||||||
child: Icon(Icons.insert_emoticon),
|
child: Icon(Icons.insert_emoticon),
|
||||||
),
|
),
|
||||||
title: Text(L10n.of(context).emoteSettings),
|
title: Text(L10n.of(context).emoteSettings),
|
||||||
onTap: () async =>
|
onTap: () async {
|
||||||
|
// okay, we need to test if there are any emote state events other than the default one
|
||||||
|
// if so, we need to be directed to a selection screen for which pack we want to look at
|
||||||
|
// otherwise, we just open the normal one.
|
||||||
|
if ((widget.room.states
|
||||||
|
.states['im.ponies.room_emotes'] ??
|
||||||
|
<String, Event>{})
|
||||||
|
.keys
|
||||||
|
.any((String s) => s.isNotEmpty)) {
|
||||||
await Navigator.of(context).push(
|
await Navigator.of(context).push(
|
||||||
AppRoute.defaultRoute(
|
AppRoute.defaultRoute(
|
||||||
context,
|
context,
|
||||||
EmotesSettingsView(room: widget.room),
|
MultipleEmotesSettingsView(
|
||||||
),
|
room: widget.room),
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
AppRoute.defaultRoute(
|
||||||
|
context,
|
||||||
|
EmotesSettingsView(room: widget.room),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
),
|
),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
|
|
|
@ -14,23 +14,25 @@ import 'chat_list.dart';
|
||||||
|
|
||||||
class EmotesSettingsView extends StatelessWidget {
|
class EmotesSettingsView extends StatelessWidget {
|
||||||
final Room room;
|
final Room room;
|
||||||
|
final String stateKey;
|
||||||
|
|
||||||
EmotesSettingsView({this.room});
|
EmotesSettingsView({this.room, this.stateKey});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AdaptivePageLayout(
|
return AdaptivePageLayout(
|
||||||
primaryPage: FocusPage.SECOND,
|
primaryPage: FocusPage.SECOND,
|
||||||
firstScaffold: ChatList(),
|
firstScaffold: ChatList(),
|
||||||
secondScaffold: EmotesSettings(room: room),
|
secondScaffold: EmotesSettings(room: room, stateKey: stateKey),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EmotesSettings extends StatefulWidget {
|
class EmotesSettings extends StatefulWidget {
|
||||||
final Room room;
|
final Room room;
|
||||||
|
final String stateKey;
|
||||||
|
|
||||||
EmotesSettings({this.room});
|
EmotesSettings({this.room, this.stateKey});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_EmotesSettingsState createState() => _EmotesSettingsState();
|
_EmotesSettingsState createState() => _EmotesSettingsState();
|
||||||
|
@ -59,21 +61,42 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
||||||
// be sure to preserve any data not in "short"
|
// be sure to preserve any data not in "short"
|
||||||
Map<String, dynamic> content;
|
Map<String, dynamic> content;
|
||||||
if (widget.room != null) {
|
if (widget.room != null) {
|
||||||
content = widget.room.getState('im.ponies.room_emotes')?.content ??
|
content = widget.room
|
||||||
|
.getState('im.ponies.room_emotes', widget.stateKey ?? '')
|
||||||
|
?.content ??
|
||||||
<String, dynamic>{};
|
<String, dynamic>{};
|
||||||
} else {
|
} else {
|
||||||
content = client.accountData['im.ponies.user_emotes']?.content ??
|
content = client.accountData['im.ponies.user_emotes']?.content ??
|
||||||
<String, dynamic>{};
|
<String, dynamic>{};
|
||||||
}
|
}
|
||||||
debugPrint(content.toString());
|
debugPrint(content.toString());
|
||||||
content['short'] = <String, String>{};
|
if (!(content['emoticons'] is Map)) {
|
||||||
for (final emote in emotes) {
|
content['emoticons'] = <String, dynamic>{};
|
||||||
content['short'][emote.emote] = emote.mxc;
|
|
||||||
}
|
}
|
||||||
|
// add / update changed emotes
|
||||||
|
final allowedShortcodes = <String>{};
|
||||||
|
for (final emote in emotes) {
|
||||||
|
allowedShortcodes.add(emote.emote);
|
||||||
|
if (!(content['emoticons'][emote.emote] is Map)) {
|
||||||
|
content['emoticons'][emote.emote] = <String, dynamic>{};
|
||||||
|
}
|
||||||
|
content['emoticons'][emote.emote]['url'] = emote.mxc;
|
||||||
|
}
|
||||||
|
// remove emotes no more needed
|
||||||
|
// we make the iterator .toList() here so that we don't get into trouble modifying the very
|
||||||
|
// thing we are iterating over
|
||||||
|
for (final shortcode in content['emoticons'].keys.toList()) {
|
||||||
|
if (!allowedShortcodes.contains(shortcode)) {
|
||||||
|
content['emoticons'].remove(shortcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// remove the old "short" key
|
||||||
|
content.remove('short');
|
||||||
debugPrint(content.toString());
|
debugPrint(content.toString());
|
||||||
if (widget.room != null) {
|
if (widget.room != null) {
|
||||||
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||||
client.sendState(widget.room.id, 'im.ponies.room_emotes', content),
|
client.sendState(widget.room.id, 'im.ponies.room_emotes', content,
|
||||||
|
widget.stateKey ?? ''),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||||
|
@ -82,6 +105,43 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _setIsGloballyActive(BuildContext context, bool active) async {
|
||||||
|
if (widget.room == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final client = Matrix.of(context).client;
|
||||||
|
final content = client.accountData['im.ponies.emote_rooms']?.content ??
|
||||||
|
<String, dynamic>{};
|
||||||
|
if (active) {
|
||||||
|
if (!(content['rooms'] is Map)) {
|
||||||
|
content['rooms'] = <String, dynamic>{};
|
||||||
|
}
|
||||||
|
if (!(content['rooms'][widget.room.id] is Map)) {
|
||||||
|
content['rooms'][widget.room.id] = <String, dynamic>{};
|
||||||
|
}
|
||||||
|
if (!(content['rooms'][widget.room.id][widget.stateKey ?? ''] is Map)) {
|
||||||
|
content['rooms'][widget.room.id]
|
||||||
|
[widget.stateKey ?? ''] = <String, dynamic>{};
|
||||||
|
}
|
||||||
|
} else if (content['rooms'] is Map &&
|
||||||
|
content['rooms'][widget.room.id] is Map) {
|
||||||
|
content['rooms'][widget.room.id].remove(widget.stateKey ?? '');
|
||||||
|
}
|
||||||
|
// and save
|
||||||
|
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||||
|
client.setAccountData(client.userID, 'im.ponies.emote_rooms', content),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGloballyActive(Client client) =>
|
||||||
|
widget.room != null &&
|
||||||
|
client.accountData['im.ponies.emote_rooms']?.content is Map &&
|
||||||
|
client.accountData['im.ponies.emote_rooms'].content['rooms'] is Map &&
|
||||||
|
client.accountData['im.ponies.emote_rooms'].content['rooms']
|
||||||
|
[widget.room.id] is Map &&
|
||||||
|
client.accountData['im.ponies.emote_rooms'].content['rooms']
|
||||||
|
[widget.room.id][widget.stateKey ?? ''] is Map;
|
||||||
|
|
||||||
bool get readonly => widget.room == null
|
bool get readonly => widget.room == null
|
||||||
? false
|
? false
|
||||||
: !(widget.room.canSendEvent('im.ponies.room_emotes'));
|
: !(widget.room.canSendEvent('im.ponies.room_emotes'));
|
||||||
|
@ -93,16 +153,31 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
||||||
emotes = <_EmoteEntry>[];
|
emotes = <_EmoteEntry>[];
|
||||||
Map<String, dynamic> emoteSource;
|
Map<String, dynamic> emoteSource;
|
||||||
if (widget.room != null) {
|
if (widget.room != null) {
|
||||||
emoteSource = widget.room.getState('im.ponies.room_emotes')?.content;
|
emoteSource = widget.room
|
||||||
|
.getState('im.ponies.room_emotes', widget.stateKey ?? '')
|
||||||
|
?.content;
|
||||||
} else {
|
} else {
|
||||||
emoteSource = client.accountData['im.ponies.user_emotes']?.content;
|
emoteSource = client.accountData['im.ponies.user_emotes']?.content;
|
||||||
}
|
}
|
||||||
if (emoteSource != null && emoteSource['short'] is Map) {
|
if (emoteSource != null) {
|
||||||
emoteSource['short'].forEach((key, value) {
|
if (emoteSource['emoticons'] is Map) {
|
||||||
if (key is String && value is String && value.startsWith('mxc://')) {
|
emoteSource['emoticons'].forEach((key, value) {
|
||||||
emotes.add(_EmoteEntry(emote: key, mxc: value));
|
if (key is String &&
|
||||||
}
|
value is Map &&
|
||||||
});
|
value['url'] is String &&
|
||||||
|
value['url'].startsWith('mxc://')) {
|
||||||
|
emotes.add(_EmoteEntry(emote: key, mxc: value['url']));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (emoteSource['short'] is Map) {
|
||||||
|
emoteSource['short'].forEach((key, value) {
|
||||||
|
if (key is String &&
|
||||||
|
value is String &&
|
||||||
|
value.startsWith('mxc://')) {
|
||||||
|
emotes.add(_EmoteEntry(emote: key, mxc: value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -166,7 +241,6 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
||||||
size: 32.0,
|
size: 32.0,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
debugPrint('blah');
|
|
||||||
if (newEmoteController.text == null ||
|
if (newEmoteController.text == null ||
|
||||||
newEmoteController.text.isEmpty ||
|
newEmoteController.text.isEmpty ||
|
||||||
newMxcController.text == null ||
|
newMxcController.text == null ||
|
||||||
|
@ -204,7 +278,19 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
||||||
vertical: 8.0,
|
vertical: 8.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!readonly)
|
if (widget.room != null)
|
||||||
|
ListTile(
|
||||||
|
title: Text(L10n.of(context).enableEmotesGlobally),
|
||||||
|
trailing: Switch(
|
||||||
|
value: isGloballyActive(client),
|
||||||
|
activeColor: Theme.of(context).primaryColor,
|
||||||
|
onChanged: (bool newValue) async {
|
||||||
|
await _setIsGloballyActive(context, newValue);
|
||||||
|
setState(() => null);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (!readonly || widget.room != null)
|
||||||
Divider(
|
Divider(
|
||||||
height: 2,
|
height: 2,
|
||||||
thickness: 2,
|
thickness: 2,
|
||||||
|
|
74
lib/views/settings_multiple_emotes.dart
Normal file
74
lib/views/settings_multiple_emotes.dart
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:famedlysdk/famedlysdk.dart';
|
||||||
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
import '../components/adaptive_page_layout.dart';
|
||||||
|
import '../utils/app_route.dart';
|
||||||
|
import 'chat_list.dart';
|
||||||
|
import 'settings_emotes.dart';
|
||||||
|
|
||||||
|
class MultipleEmotesSettingsView extends StatelessWidget {
|
||||||
|
final Room room;
|
||||||
|
|
||||||
|
MultipleEmotesSettingsView({this.room});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return AdaptivePageLayout(
|
||||||
|
primaryPage: FocusPage.SECOND,
|
||||||
|
firstScaffold: ChatList(),
|
||||||
|
secondScaffold: MultipleEmotesSettings(room: room),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultipleEmotesSettings extends StatelessWidget {
|
||||||
|
final Room room;
|
||||||
|
|
||||||
|
MultipleEmotesSettings({this.room});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(L10n.of(context).emotePacks),
|
||||||
|
),
|
||||||
|
body: StreamBuilder(
|
||||||
|
stream: room.onUpdate.stream,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final packs =
|
||||||
|
room.states.states['im.ponies.room_emotes'] ?? <String, Event>{};
|
||||||
|
if (!packs.containsKey('')) {
|
||||||
|
packs[''] = null;
|
||||||
|
}
|
||||||
|
final keys = packs.keys.toList();
|
||||||
|
keys.sort();
|
||||||
|
return ListView.separated(
|
||||||
|
separatorBuilder: (BuildContext context, int i) => Container(),
|
||||||
|
itemCount: keys.length,
|
||||||
|
itemBuilder: (BuildContext context, int i) {
|
||||||
|
final event = packs[keys[i]];
|
||||||
|
var packName = keys[i].isNotEmpty ? keys[i] : 'Default Pack';
|
||||||
|
if (event != null && event.content['pack'] is Map) {
|
||||||
|
if (event.content['pack']['displayname'] is String) {
|
||||||
|
packName = event.content['pack']['displayname'];
|
||||||
|
} else if (event.content['pack']['name'] is String) {
|
||||||
|
packName = event.content['pack']['name'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ListTile(
|
||||||
|
title: Text(packName),
|
||||||
|
onTap: () async {
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
AppRoute.defaultRoute(
|
||||||
|
context,
|
||||||
|
EmotesSettingsView(room: room, stateKey: keys[i]),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
56
pubspec.lock
56
pubspec.lock
|
@ -49,7 +49,7 @@ packages:
|
||||||
name: async
|
name: async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.0-nullsafety.1"
|
version: "2.4.2"
|
||||||
base58check:
|
base58check:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -63,7 +63,7 @@ packages:
|
||||||
name: boolean_selector
|
name: boolean_selector
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-nullsafety.1"
|
version: "2.0.0"
|
||||||
bot_toast:
|
bot_toast:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -91,14 +91,14 @@ packages:
|
||||||
name: characters
|
name: characters
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0-nullsafety.3"
|
version: "1.0.0"
|
||||||
charcode:
|
charcode:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: charcode
|
name: charcode
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0-nullsafety.1"
|
version: "1.1.3"
|
||||||
cli_util:
|
cli_util:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -112,14 +112,14 @@ packages:
|
||||||
name: clock
|
name: clock
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0-nullsafety.1"
|
version: "1.0.1"
|
||||||
collection:
|
collection:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: collection
|
name: collection
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.15.0-nullsafety.3"
|
version: "1.14.13"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -175,13 +175,13 @@ packages:
|
||||||
name: fake_async
|
name: fake_async
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0-nullsafety.1"
|
version: "1.1.0"
|
||||||
famedlysdk:
|
famedlysdk:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
path: "."
|
path: "."
|
||||||
ref: "5019ebfeb56f0789ab4cc8d27ccda663156b5d68"
|
ref: "84cc925b08e97098d00c54fff9c1244f91055de3"
|
||||||
resolved-ref: "5019ebfeb56f0789ab4cc8d27ccda663156b5d68"
|
resolved-ref: "84cc925b08e97098d00c54fff9c1244f91055de3"
|
||||||
url: "https://gitlab.com/famedly/famedlysdk.git"
|
url: "https://gitlab.com/famedly/famedlysdk.git"
|
||||||
source: git
|
source: git
|
||||||
version: "0.0.1"
|
version: "0.0.1"
|
||||||
|
@ -456,7 +456,7 @@ packages:
|
||||||
name: js
|
name: js
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.3-nullsafety.1"
|
version: "0.6.2"
|
||||||
localstorage:
|
localstorage:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -484,7 +484,7 @@ packages:
|
||||||
name: matcher
|
name: matcher
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.12.10-nullsafety.1"
|
version: "0.12.8"
|
||||||
matrix_file_e2ee:
|
matrix_file_e2ee:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -512,7 +512,7 @@ packages:
|
||||||
name: meta
|
name: meta
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0-nullsafety.3"
|
version: "1.1.8"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -605,7 +605,7 @@ packages:
|
||||||
name: path
|
name: path
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0-nullsafety.1"
|
version: "1.7.0"
|
||||||
path_provider:
|
path_provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -647,7 +647,7 @@ packages:
|
||||||
name: pedantic
|
name: pedantic
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0-nullsafety.1"
|
version: "1.9.0"
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -689,7 +689,7 @@ packages:
|
||||||
name: pool
|
name: pool
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0-nullsafety.1"
|
version: "1.4.0"
|
||||||
process:
|
process:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -792,21 +792,21 @@ packages:
|
||||||
name: source_map_stack_trace
|
name: source_map_stack_trace
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-nullsafety.2"
|
version: "2.0.0"
|
||||||
source_maps:
|
source_maps:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_maps
|
name: source_maps
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.10.10-nullsafety.1"
|
version: "0.10.9"
|
||||||
source_span:
|
source_span:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: source_span
|
name: source_span
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.8.0-nullsafety.2"
|
version: "1.7.0"
|
||||||
sqflite:
|
sqflite:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -841,21 +841,21 @@ packages:
|
||||||
name: stack_trace
|
name: stack_trace
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.10.0-nullsafety.1"
|
version: "1.9.5"
|
||||||
stream_channel:
|
stream_channel:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: stream_channel
|
name: stream_channel
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-nullsafety.1"
|
version: "2.0.0"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: string_scanner
|
name: string_scanner
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0-nullsafety.1"
|
version: "1.0.5"
|
||||||
synchronized:
|
synchronized:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -869,35 +869,35 @@ packages:
|
||||||
name: term_glyph
|
name: term_glyph
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0-nullsafety.1"
|
version: "1.1.0"
|
||||||
test:
|
test:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test
|
name: test
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.16.0-nullsafety.5"
|
version: "1.15.2"
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.19-nullsafety.2"
|
version: "0.2.17"
|
||||||
test_core:
|
test_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_core
|
name: test_core
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.12-nullsafety.5"
|
version: "0.3.10"
|
||||||
typed_data:
|
typed_data:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: typed_data
|
name: typed_data
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.0-nullsafety.3"
|
version: "1.2.0"
|
||||||
universal_html:
|
universal_html:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -981,7 +981,7 @@ packages:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0-nullsafety.3"
|
version: "2.0.8"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -1053,5 +1053,5 @@ packages:
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.2"
|
version: "0.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.10.0-110 <2.11.0"
|
dart: ">=2.9.0 <3.0.0"
|
||||||
flutter: ">=1.20.0 <2.0.0"
|
flutter: ">=1.20.0 <2.0.0"
|
||||||
|
|
|
@ -27,7 +27,7 @@ dependencies:
|
||||||
famedlysdk:
|
famedlysdk:
|
||||||
git:
|
git:
|
||||||
url: https://gitlab.com/famedly/famedlysdk.git
|
url: https://gitlab.com/famedly/famedlysdk.git
|
||||||
ref: 5019ebfeb56f0789ab4cc8d27ccda663156b5d68
|
ref: 84cc925b08e97098d00c54fff9c1244f91055de3
|
||||||
|
|
||||||
localstorage: ^3.0.1+4
|
localstorage: ^3.0.1+4
|
||||||
memoryfilepicker: ^0.1.3
|
memoryfilepicker: ^0.1.3
|
||||||
|
|
Loading…
Reference in a new issue