Soru/moor
This commit is contained in:
parent
79a306351e
commit
f594c7005d
55 changed files with 1034 additions and 1133 deletions
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:famedlysdk/famedlysdk.dart';
|
||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
||||
import 'package:fluffychat/components/matrix.dart';
|
||||
import 'package:fluffychat/l10n/l10n.dart';
|
||||
|
|
@ -21,7 +20,7 @@ class AppInfoView extends StatelessWidget {
|
|||
class AppInfo extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Client client = Matrix.of(context).client;
|
||||
var client = Matrix.of(context).client;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(L10n.of(context).accountInformations),
|
||||
|
|
@ -29,43 +28,39 @@ class AppInfo extends StatelessWidget {
|
|||
body: ListView(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text(L10n.of(context).yourOwnUsername + ":"),
|
||||
title: Text(L10n.of(context).yourOwnUsername + ':'),
|
||||
subtitle: Text(client.userID),
|
||||
),
|
||||
ListTile(
|
||||
title: Text("Homeserver:"),
|
||||
title: Text('Homeserver:'),
|
||||
subtitle: Text(client.homeserver),
|
||||
),
|
||||
ListTile(
|
||||
title: Text("Supported versions:"),
|
||||
subtitle: Text(client.matrixVersions.toString()),
|
||||
),
|
||||
ListTile(
|
||||
title: Text("Device name:"),
|
||||
title: Text('Device name:'),
|
||||
subtitle: Text(client.deviceName),
|
||||
),
|
||||
ListTile(
|
||||
title: Text("Device ID:"),
|
||||
title: Text('Device ID:'),
|
||||
subtitle: Text(client.deviceID),
|
||||
),
|
||||
ListTile(
|
||||
title: Text("Encryption enabled:"),
|
||||
title: Text('Encryption enabled:'),
|
||||
subtitle: Text(client.encryptionEnabled.toString()),
|
||||
),
|
||||
if (client.encryptionEnabled)
|
||||
Column(
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
title: Text("Your public fingerprint key:"),
|
||||
title: Text('Your public fingerprint key:'),
|
||||
subtitle: Text(client.fingerprintKey.beautified),
|
||||
),
|
||||
ListTile(
|
||||
title: Text("Your public identity key:"),
|
||||
title: Text('Your public identity key:'),
|
||||
subtitle: Text(client.identityKey.beautified),
|
||||
),
|
||||
ListTile(
|
||||
title: Text("LibOlm version:"),
|
||||
subtitle: Text(olm.get_library_version().join(".")),
|
||||
title: Text('LibOlm version:'),
|
||||
subtitle: Text(olm.get_library_version().join('.')),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ class _ArchiveState extends State<Archive> {
|
|||
),
|
||||
secondScaffold: Scaffold(
|
||||
body: Center(
|
||||
child: Image.asset("assets/logo.png", width: 100, height: 100),
|
||||
child: Image.asset('assets/logo.png', width: 100, height: 100),
|
||||
),
|
||||
),
|
||||
primaryPage: FocusPage.FIRST,
|
||||
|
|
|
|||
|
|
@ -14,8 +14,9 @@ class AuthWebView extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final String url = Matrix.of(context).client.homeserver +
|
||||
"/_matrix/client/r0/auth/$authType/fallback/web?session=$session";
|
||||
final url =
|
||||
'/_matrix/client/r0/auth/$authType/fallback/web?session=$session' +
|
||||
Matrix.of(context).client.homeserver;
|
||||
if (kIsWeb) launch(url);
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class _ChatState extends State<_Chat> {
|
|||
|
||||
MatrixState matrix;
|
||||
|
||||
String seenByText = "";
|
||||
String seenByText = '';
|
||||
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
|
|
@ -77,15 +77,19 @@ class _ChatState extends State<_Chat> {
|
|||
|
||||
final int _loadHistoryCount = 100;
|
||||
|
||||
String inputText = "";
|
||||
String inputText = '';
|
||||
|
||||
bool get _canLoadMore => timeline.events.last.type != EventTypes.RoomCreate;
|
||||
|
||||
void requestHistory() async {
|
||||
if (_canLoadMore) {
|
||||
setState(() => this._loadingHistory = true);
|
||||
await timeline.requestHistory(historyCount: _loadHistoryCount);
|
||||
if (mounted) setState(() => this._loadingHistory = false);
|
||||
setState(() => _loadingHistory = true);
|
||||
try {
|
||||
await timeline.requestHistory(historyCount: _loadHistoryCount);
|
||||
} catch (e) {
|
||||
debugPrint('Error loading history: ' + e.toString());
|
||||
}
|
||||
if (mounted) setState(() => _loadingHistory = false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,9 +118,9 @@ class _ChatState extends State<_Chat> {
|
|||
void updateView() {
|
||||
if (!mounted) return;
|
||||
|
||||
String seenByText = "";
|
||||
var seenByText = '';
|
||||
if (timeline.events.isNotEmpty) {
|
||||
List lastReceipts = List.from(timeline.events.first.receipts);
|
||||
var lastReceipts = List.from(timeline.events.first.receipts);
|
||||
lastReceipts.removeWhere((r) =>
|
||||
r.user.id == room.client.userID ||
|
||||
r.user.id == timeline.events.first.senderId);
|
||||
|
|
@ -147,7 +151,7 @@ class _ChatState extends State<_Chat> {
|
|||
unawaited(room.sendReadReceipt(timeline.events.first.eventId));
|
||||
}
|
||||
if (timeline.events.length < _loadHistoryCount) {
|
||||
this.requestHistory();
|
||||
requestHistory();
|
||||
}
|
||||
}
|
||||
updateView();
|
||||
|
|
@ -158,7 +162,7 @@ class _ChatState extends State<_Chat> {
|
|||
void dispose() {
|
||||
timeline?.cancelSubscriptions();
|
||||
timeline = null;
|
||||
matrix.activeRoomId = "";
|
||||
matrix.activeRoomId = '';
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -167,12 +171,12 @@ class _ChatState extends State<_Chat> {
|
|||
void send() {
|
||||
if (sendController.text.isEmpty) return;
|
||||
room.sendTextEvent(sendController.text, inReplyTo: replyEvent);
|
||||
sendController.text = "";
|
||||
sendController.text = '';
|
||||
if (replyEvent != null) {
|
||||
setState(() => replyEvent = null);
|
||||
}
|
||||
|
||||
setState(() => inputText = "");
|
||||
setState(() => inputText = '');
|
||||
}
|
||||
|
||||
void sendFileAction(BuildContext context) async {
|
||||
|
|
@ -180,7 +184,7 @@ class _ChatState extends State<_Chat> {
|
|||
BotToast.showText(text: L10n.of(context).notSupportedInWeb);
|
||||
return;
|
||||
}
|
||||
File file = await FilePicker.getFile();
|
||||
var file = await FilePicker.getFile();
|
||||
if (file == null) return;
|
||||
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
room.sendFileEvent(
|
||||
|
|
@ -194,7 +198,7 @@ class _ChatState extends State<_Chat> {
|
|||
BotToast.showText(text: L10n.of(context).notSupportedInWeb);
|
||||
return;
|
||||
}
|
||||
File file = await ImagePicker.pickImage(
|
||||
var file = await ImagePicker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
imageQuality: 50,
|
||||
maxWidth: 1600,
|
||||
|
|
@ -212,7 +216,7 @@ class _ChatState extends State<_Chat> {
|
|||
BotToast.showText(text: L10n.of(context).notSupportedInWeb);
|
||||
return;
|
||||
}
|
||||
File file = await ImagePicker.pickImage(
|
||||
var file = await ImagePicker.pickImage(
|
||||
source: ImageSource.camera,
|
||||
imageQuality: 50,
|
||||
maxWidth: 1600,
|
||||
|
|
@ -233,7 +237,7 @@ class _ChatState extends State<_Chat> {
|
|||
onFinished: (r) => result = r,
|
||||
));
|
||||
if (result == null) return;
|
||||
final File audioFile = File(result);
|
||||
final audioFile = File(result);
|
||||
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
room.sendAudioEvent(
|
||||
MatrixFile(bytes: audioFile.readAsBytesSync(), path: audioFile.path),
|
||||
|
|
@ -242,12 +246,12 @@ class _ChatState extends State<_Chat> {
|
|||
}
|
||||
|
||||
String _getSelectedEventString(BuildContext context) {
|
||||
String copyString = "";
|
||||
var copyString = '';
|
||||
if (selectedEvents.length == 1) {
|
||||
return selectedEvents.first.getLocalizedBody(L10n.of(context));
|
||||
}
|
||||
for (Event event in selectedEvents) {
|
||||
if (copyString.isNotEmpty) copyString += "\n\n";
|
||||
for (var event in selectedEvents) {
|
||||
if (copyString.isNotEmpty) copyString += '\n\n';
|
||||
copyString +=
|
||||
event.getLocalizedBody(L10n.of(context), withSenderNamePrefix: true);
|
||||
}
|
||||
|
|
@ -260,12 +264,12 @@ class _ChatState extends State<_Chat> {
|
|||
}
|
||||
|
||||
void redactEventsAction(BuildContext context) async {
|
||||
bool confirmed = await SimpleDialogs(context).askConfirmation(
|
||||
var confirmed = await SimpleDialogs(context).askConfirmation(
|
||||
titleText: L10n.of(context).messageWillBeRemovedWarning,
|
||||
confirmText: L10n.of(context).remove,
|
||||
);
|
||||
if (!confirmed) return;
|
||||
for (Event event in selectedEvents) {
|
||||
for (var event in selectedEvents) {
|
||||
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
event.status > 0 ? event.redact() : event.remove());
|
||||
}
|
||||
|
|
@ -273,7 +277,7 @@ class _ChatState extends State<_Chat> {
|
|||
}
|
||||
|
||||
bool get canRedactSelectedEvents {
|
||||
for (Event event in selectedEvents) {
|
||||
for (var event in selectedEvents) {
|
||||
if (event.canRedact == false) return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -284,8 +288,8 @@ class _ChatState extends State<_Chat> {
|
|||
Matrix.of(context).shareContent = selectedEvents.first.content;
|
||||
} else {
|
||||
Matrix.of(context).shareContent = {
|
||||
"msgtype": "m.text",
|
||||
"body": _getSelectedEventString(context),
|
||||
'msgtype': 'm.text',
|
||||
'body': _getSelectedEventString(context),
|
||||
};
|
||||
}
|
||||
setState(() => selectedEvents.clear());
|
||||
|
|
@ -308,7 +312,7 @@ class _ChatState extends State<_Chat> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
matrix = Matrix.of(context);
|
||||
Client client = matrix.client;
|
||||
var client = matrix.client;
|
||||
room ??= client.getRoomById(widget.id);
|
||||
if (room == null) {
|
||||
return Scaffold(
|
||||
|
|
@ -326,8 +330,8 @@ class _ChatState extends State<_Chat> {
|
|||
SimpleDialogs(context).tryRequestWithLoadingDialog(room.join());
|
||||
}
|
||||
|
||||
String typingText = "";
|
||||
List<User> typingUsers = room.typingUsers;
|
||||
var typingText = '';
|
||||
var typingUsers = room.typingUsers;
|
||||
typingUsers.removeWhere((User u) => u.id == client.userID);
|
||||
|
||||
if (typingUsers.length == 1) {
|
||||
|
|
@ -616,22 +620,22 @@ class _ChatState extends State<_Chat> {
|
|||
PopupMenuButton<String>(
|
||||
icon: Icon(Icons.add),
|
||||
onSelected: (String choice) async {
|
||||
if (choice == "file") {
|
||||
if (choice == 'file') {
|
||||
sendFileAction(context);
|
||||
} else if (choice == "image") {
|
||||
} else if (choice == 'image') {
|
||||
sendImageAction(context);
|
||||
}
|
||||
if (choice == "camera") {
|
||||
if (choice == 'camera') {
|
||||
openCameraAction(context);
|
||||
}
|
||||
if (choice == "voice") {
|
||||
if (choice == 'voice') {
|
||||
voiceMessageAction(context);
|
||||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) =>
|
||||
<PopupMenuEntry<String>>[
|
||||
PopupMenuItem<String>(
|
||||
value: "file",
|
||||
value: 'file',
|
||||
child: ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.green,
|
||||
|
|
@ -644,7 +648,7 @@ class _ChatState extends State<_Chat> {
|
|||
),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: "image",
|
||||
value: 'image',
|
||||
child: ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.blue,
|
||||
|
|
@ -657,7 +661,7 @@ class _ChatState extends State<_Chat> {
|
|||
),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: "camera",
|
||||
value: 'camera',
|
||||
child: ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.purple,
|
||||
|
|
@ -670,7 +674,7 @@ class _ChatState extends State<_Chat> {
|
|||
),
|
||||
),
|
||||
PopupMenuItem<String>(
|
||||
value: "voice",
|
||||
value: 'voice',
|
||||
child: ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Colors.red,
|
||||
|
|
@ -708,20 +712,20 @@ class _ChatState extends State<_Chat> {
|
|||
border: InputBorder.none,
|
||||
),
|
||||
onChanged: (String text) {
|
||||
this.typingCoolDown?.cancel();
|
||||
this.typingCoolDown =
|
||||
typingCoolDown?.cancel();
|
||||
typingCoolDown =
|
||||
Timer(Duration(seconds: 2), () {
|
||||
this.typingCoolDown = null;
|
||||
this.currentlyTyping = false;
|
||||
typingCoolDown = null;
|
||||
currentlyTyping = false;
|
||||
room.sendTypingInfo(false);
|
||||
});
|
||||
this.typingTimeout ??=
|
||||
typingTimeout ??=
|
||||
Timer(Duration(seconds: 30), () {
|
||||
this.typingTimeout = null;
|
||||
this.currentlyTyping = false;
|
||||
typingTimeout = null;
|
||||
currentlyTyping = false;
|
||||
});
|
||||
if (!this.currentlyTyping) {
|
||||
this.currentlyTyping = true;
|
||||
if (!currentlyTyping) {
|
||||
currentlyTyping = true;
|
||||
room.sendTypingInfo(true,
|
||||
timeout: Duration(seconds: 30)
|
||||
.inMilliseconds);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:famedlysdk/famedlysdk.dart';
|
||||
import 'package:fluffychat/components/adaptive_page_layout.dart';
|
||||
import 'package:fluffychat/components/chat_settings_popup_menu.dart';
|
||||
|
|
@ -30,11 +28,12 @@ class ChatDetails extends StatefulWidget {
|
|||
class _ChatDetailsState extends State<ChatDetails> {
|
||||
List<User> members;
|
||||
void setDisplaynameAction(BuildContext context) async {
|
||||
final String displayname = await SimpleDialogs(context).enterText(
|
||||
var enterText = SimpleDialogs(context).enterText(
|
||||
titleText: L10n.of(context).changeTheNameOfTheGroup,
|
||||
labelText: L10n.of(context).changeTheNameOfTheGroup,
|
||||
hintText: widget.room.getLocalizedDisplayname(L10n.of(context)),
|
||||
);
|
||||
final displayname = await enterText;
|
||||
if (displayname == null) return;
|
||||
final success = await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
widget.room.setName(displayname),
|
||||
|
|
@ -45,26 +44,26 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
}
|
||||
|
||||
void setCanonicalAliasAction(context) async {
|
||||
final String s = await SimpleDialogs(context).enterText(
|
||||
final s = await SimpleDialogs(context).enterText(
|
||||
titleText: L10n.of(context).setInvitationLink,
|
||||
labelText: L10n.of(context).setInvitationLink,
|
||||
hintText: L10n.of(context).alias.toLowerCase(),
|
||||
prefixText: "#",
|
||||
suffixText: ":" + widget.room.client.userID.domain,
|
||||
prefixText: '#',
|
||||
suffixText: ':' + widget.room.client.userID.domain,
|
||||
);
|
||||
if (s == null) return;
|
||||
final String domain = widget.room.client.userID.domain;
|
||||
final String canonicalAlias = "%23" + s + "%3A" + domain;
|
||||
final Event aliasEvent = widget.room.getState("m.room.aliases", domain);
|
||||
final List aliases =
|
||||
aliasEvent != null ? aliasEvent.content["aliases"] ?? [] : [];
|
||||
final domain = widget.room.client.userID.domain;
|
||||
final canonicalAlias = '%23' + s + '%3A' + domain;
|
||||
final aliasEvent = widget.room.getState('m.room.aliases', domain);
|
||||
final aliases =
|
||||
aliasEvent != null ? aliasEvent.content['aliases'] ?? [] : [];
|
||||
if (aliases.indexWhere((s) => s == canonicalAlias) == -1) {
|
||||
List<String> newAliases = List.from(aliases);
|
||||
var newAliases = List<String>.from(aliases);
|
||||
newAliases.add(canonicalAlias);
|
||||
final response = await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
widget.room.client.jsonRequest(
|
||||
type: HTTPType.GET,
|
||||
action: "/client/r0/directory/room/$canonicalAlias",
|
||||
action: '/client/r0/directory/room/$canonicalAlias',
|
||||
),
|
||||
);
|
||||
if (response == false) {
|
||||
|
|
@ -72,8 +71,8 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
widget.room.client.jsonRequest(
|
||||
type: HTTPType.PUT,
|
||||
action: "/client/r0/directory/room/$canonicalAlias",
|
||||
data: {"room_id": widget.room.id}),
|
||||
action: '/client/r0/directory/room/$canonicalAlias',
|
||||
data: {'room_id': widget.room.id}),
|
||||
);
|
||||
if (success == false) return;
|
||||
}
|
||||
|
|
@ -82,13 +81,13 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
widget.room.client.jsonRequest(
|
||||
type: HTTPType.PUT,
|
||||
action:
|
||||
"/client/r0/rooms/${widget.room.id}/state/m.room.canonical_alias",
|
||||
data: {"alias": "#$s:$domain"}),
|
||||
'/client/r0/rooms/${widget.room.id}/state/m.room.canonical_alias',
|
||||
data: {'alias': '#$s:$domain'}),
|
||||
);
|
||||
}
|
||||
|
||||
void setTopicAction(BuildContext context) async {
|
||||
final String displayname = await SimpleDialogs(context).enterText(
|
||||
final displayname = await SimpleDialogs(context).enterText(
|
||||
titleText: L10n.of(context).setGroupDescription,
|
||||
labelText: L10n.of(context).setGroupDescription,
|
||||
hintText: (widget.room.topic?.isNotEmpty ?? false)
|
||||
|
|
@ -106,7 +105,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
}
|
||||
|
||||
void setAvatarAction(BuildContext context) async {
|
||||
final File tempFile = await ImagePicker.pickImage(
|
||||
final tempFile = await ImagePicker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
imageQuality: 50,
|
||||
maxWidth: 1600,
|
||||
|
|
@ -145,9 +144,9 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
}
|
||||
members ??= widget.room.getParticipants();
|
||||
members.removeWhere((u) => u.membership == Membership.leave);
|
||||
final int actualMembersCount =
|
||||
final actualMembersCount =
|
||||
widget.room.mInvitedMemberCount + widget.room.mJoinedMemberCount;
|
||||
final bool canRequestMoreMembers = members.length < actualMembersCount;
|
||||
final canRequestMoreMembers = members.length < actualMembersCount;
|
||||
return AdaptivePageLayout(
|
||||
primaryPage: FocusPage.SECOND,
|
||||
firstScaffold: ChatList(
|
||||
|
|
@ -189,7 +188,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
backgroundColor: Theme.of(context).appBarTheme.color,
|
||||
flexibleSpace: FlexibleSpaceBar(
|
||||
background: ContentBanner(widget.room.avatar,
|
||||
onEdit: widget.room.canSendEvent("m.room.avatar") &&
|
||||
onEdit: widget.room.canSendEvent('m.room.avatar') &&
|
||||
!kIsWeb
|
||||
? () => setAvatarAction(context)
|
||||
: null),
|
||||
|
|
@ -204,7 +203,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
ListTile(
|
||||
leading: widget.room.canSendEvent("m.room.topic")
|
||||
leading: widget.room.canSendEvent('m.room.topic')
|
||||
? CircleAvatar(
|
||||
backgroundColor: Theme.of(context)
|
||||
.scaffoldBackgroundColor,
|
||||
|
|
@ -213,7 +212,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
)
|
||||
: null,
|
||||
title: Text(
|
||||
"${L10n.of(context).groupDescription}:",
|
||||
'${L10n.of(context).groupDescription}:',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontWeight: FontWeight.bold)),
|
||||
|
|
@ -230,7 +229,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
.color,
|
||||
),
|
||||
),
|
||||
onTap: widget.room.canSendEvent("m.room.topic")
|
||||
onTap: widget.room.canSendEvent('m.room.topic')
|
||||
? () => setTopicAction(context)
|
||||
: null,
|
||||
),
|
||||
|
|
@ -244,7 +243,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
),
|
||||
),
|
||||
),
|
||||
if (widget.room.canSendEvent("m.room.name"))
|
||||
if (widget.room.canSendEvent('m.room.name'))
|
||||
ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor:
|
||||
|
|
@ -259,7 +258,7 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||
onTap: () => setDisplaynameAction(context),
|
||||
),
|
||||
if (widget.room
|
||||
.canSendEvent("m.room.canonical_alias") &&
|
||||
.canSendEvent('m.room.canonical_alias') &&
|
||||
widget.room.joinRules == JoinRules.public)
|
||||
ListTile(
|
||||
leading: CircleAvatar(
|
||||
|
|
|
|||
|
|
@ -50,14 +50,14 @@ class _ChatEncryptionSettingsState extends State<ChatEncryptionSettings> {
|
|||
if (snapshot.hasError) {
|
||||
return Center(
|
||||
child: Text(L10n.of(context).oopsSomethingWentWrong +
|
||||
": " +
|
||||
': ' +
|
||||
snapshot.error.toString()),
|
||||
);
|
||||
}
|
||||
if (!snapshot.hasData) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
}
|
||||
final List<DeviceKeys> deviceKeys = snapshot.data;
|
||||
final deviceKeys = snapshot.data;
|
||||
return ListView.separated(
|
||||
separatorBuilder: (BuildContext context, int i) =>
|
||||
Divider(height: 1),
|
||||
|
|
@ -96,7 +96,7 @@ class _ChatEncryptionSettingsState extends State<ChatEncryptionSettings> {
|
|||
),
|
||||
subtitle: Text(
|
||||
deviceKeys[i]
|
||||
.keys["ed25519:${deviceKeys[i].deviceId}"]
|
||||
.keys['ed25519:${deviceKeys[i].deviceId}']
|
||||
.beautified,
|
||||
style: TextStyle(
|
||||
color:
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class ChatListView extends StatelessWidget {
|
|||
firstScaffold: ChatList(),
|
||||
secondScaffold: Scaffold(
|
||||
body: Center(
|
||||
child: Image.asset("assets/logo.png", width: 100, height: 100),
|
||||
child: Image.asset('assets/logo.png', width: 100, height: 100),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
@ -62,7 +62,7 @@ class _ChatListState extends State<ChatList> {
|
|||
final ScrollController _scrollController = ScrollController();
|
||||
|
||||
Future<void> waitForFirstSync(BuildContext context) async {
|
||||
Client client = Matrix.of(context).client;
|
||||
var client = Matrix.of(context).client;
|
||||
if (client.prevBatch?.isEmpty ?? true) {
|
||||
await client.onFirstSync.stream.first;
|
||||
}
|
||||
|
|
@ -106,7 +106,7 @@ class _ChatListState extends State<ChatList> {
|
|||
publicRoomsResponse = newPublicRoomsResponse;
|
||||
if (searchController.text.isNotEmpty &&
|
||||
searchController.text.isValidMatrixId &&
|
||||
searchController.text.sigil == "#") {
|
||||
searchController.text.sigil == '#') {
|
||||
publicRoomsResponse.publicRooms.add(
|
||||
PublicRoomEntry(
|
||||
aliases: [searchController.text],
|
||||
|
|
@ -134,11 +134,11 @@ class _ChatListState extends State<ChatList> {
|
|||
if (Navigator.of(context).canPop()) {
|
||||
Navigator.of(context).popUntil((r) => r.isFirst);
|
||||
}
|
||||
final File file = File(files.first.path);
|
||||
final file = File(files.first.path);
|
||||
|
||||
Matrix.of(context).shareContent = {
|
||||
"msgtype": "chat.fluffy.shared_file",
|
||||
"file": MatrixFile(
|
||||
'msgtype': 'chat.fluffy.shared_file',
|
||||
'file': MatrixFile(
|
||||
bytes: file.readAsBytesSync(),
|
||||
path: file.path,
|
||||
),
|
||||
|
|
@ -150,13 +150,13 @@ class _ChatListState extends State<ChatList> {
|
|||
if (Navigator.of(context).canPop()) {
|
||||
Navigator.of(context).popUntil((r) => r.isFirst);
|
||||
}
|
||||
if (text.startsWith("https://matrix.to/#/")) {
|
||||
if (text.startsWith('https://matrix.to/#/')) {
|
||||
UrlLauncher(context, text).openMatrixToUrl();
|
||||
return;
|
||||
}
|
||||
Matrix.of(context).shareContent = {
|
||||
"msgtype": "m.text",
|
||||
"body": text,
|
||||
'msgtype': 'm.text',
|
||||
'body': text,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -204,8 +204,8 @@ class _ChatListState extends State<ChatList> {
|
|||
action:
|
||||
'/client/r0/presence/${Matrix.of(context).client.userID}/status',
|
||||
data: {
|
||||
"presence": "online",
|
||||
"status_msg": status,
|
||||
'presence': 'online',
|
||||
'status_msg': status,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
@ -288,7 +288,7 @@ class _ChatListState extends State<ChatList> {
|
|||
Navigator.of(context).pop();
|
||||
Share.share(L10n.of(context).inviteText(
|
||||
Matrix.of(context).client.userID,
|
||||
"https://matrix.to/#/${Matrix.of(context).client.userID}"));
|
||||
'https://matrix.to/#/${Matrix.of(context).client.userID}'));
|
||||
},
|
||||
),
|
||||
],
|
||||
|
|
@ -381,13 +381,13 @@ class _ChatListState extends State<ChatList> {
|
|||
future: waitForFirstSync(context),
|
||||
builder: (BuildContext context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
List<Room> rooms = List<Room>.from(
|
||||
var rooms = List<Room>.from(
|
||||
Matrix.of(context).client.rooms);
|
||||
rooms.removeWhere((Room room) =>
|
||||
searchMode &&
|
||||
!room.displayname.toLowerCase().contains(
|
||||
searchController.text.toLowerCase() ??
|
||||
""));
|
||||
''));
|
||||
if (rooms.isEmpty &&
|
||||
(!searchMode ||
|
||||
publicRoomsResponse == null)) {
|
||||
|
|
@ -410,10 +410,10 @@ class _ChatListState extends State<ChatList> {
|
|||
),
|
||||
);
|
||||
}
|
||||
final int publicRoomsCount =
|
||||
final publicRoomsCount =
|
||||
(publicRoomsResponse?.publicRooms?.length ??
|
||||
0);
|
||||
final int totalCount =
|
||||
final totalCount =
|
||||
rooms.length + publicRoomsCount;
|
||||
return ListView.separated(
|
||||
controller: _scrollController,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import 'package:fluffychat/views/sign_up.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class HomeserverPicker extends StatelessWidget {
|
||||
_setHomeserverAction(BuildContext context) async {
|
||||
Future<void> _setHomeserverAction(BuildContext context) async {
|
||||
final homeserver = await SimpleDialogs(context).enterText(
|
||||
titleText: L10n.of(context).enterYourHomeserver,
|
||||
hintText: Matrix.defaultHomeserver,
|
||||
|
|
@ -17,7 +17,7 @@ class HomeserverPicker extends StatelessWidget {
|
|||
_checkHomeserverAction(homeserver, context);
|
||||
}
|
||||
|
||||
_checkHomeserverAction(String homeserver, BuildContext context) async {
|
||||
void _checkHomeserverAction(String homeserver, BuildContext context) async {
|
||||
if (!homeserver.startsWith('https://')) {
|
||||
homeserver = 'https://$homeserver';
|
||||
}
|
||||
|
|
@ -40,7 +40,7 @@ class HomeserverPicker extends StatelessWidget {
|
|||
children: <Widget>[
|
||||
Hero(
|
||||
tag: 'loginBanner',
|
||||
child: Image.asset("assets/fluffychat-banner.png"),
|
||||
child: Image.asset('assets/fluffychat-banner.png'),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
|
|
|
|||
|
|
@ -27,17 +27,18 @@ class _InvitationSelectionState extends State<InvitationSelection> {
|
|||
Timer coolDown;
|
||||
|
||||
Future<List<User>> getContacts(BuildContext context) async {
|
||||
final Client client = Matrix.of(context).client;
|
||||
List<User> participants = await widget.room.requestParticipants();
|
||||
var client2 = Matrix.of(context).client;
|
||||
final client = client2;
|
||||
var participants = await widget.room.requestParticipants();
|
||||
participants.removeWhere(
|
||||
(u) => ![Membership.join, Membership.invite].contains(u.membership),
|
||||
);
|
||||
List<User> contacts = [];
|
||||
Map<String, bool> userMap = {};
|
||||
for (int i = 0; i < client.rooms.length; i++) {
|
||||
List<User> roomUsers = client.rooms[i].getParticipants();
|
||||
var contacts = <User>[];
|
||||
var userMap = <String, bool>{};
|
||||
for (var i = 0; i < client.rooms.length; i++) {
|
||||
var roomUsers = client.rooms[i].getParticipants();
|
||||
|
||||
for (int j = 0; j < roomUsers.length; j++) {
|
||||
for (var j = 0; j < roomUsers.length; j++) {
|
||||
if (userMap[roomUsers[j].id] != true &&
|
||||
participants.indexWhere((u) => u.id == roomUsers[j].id) == -1) {
|
||||
contacts.add(roomUsers[j]);
|
||||
|
|
@ -81,41 +82,41 @@ class _InvitationSelectionState extends State<InvitationSelection> {
|
|||
if (currentSearchTerm.isEmpty) return;
|
||||
if (loading) return;
|
||||
setState(() => loading = true);
|
||||
final MatrixState matrix = Matrix.of(context);
|
||||
final matrix = Matrix.of(context);
|
||||
final response = await SimpleDialogs(context).tryRequestWithErrorToast(
|
||||
matrix.client.jsonRequest(
|
||||
type: HTTPType.POST,
|
||||
action: "/client/r0/user_directory/search",
|
||||
action: '/client/r0/user_directory/search',
|
||||
data: {
|
||||
"search_term": text,
|
||||
"limit": 10,
|
||||
'search_term': text,
|
||||
'limit': 10,
|
||||
}),
|
||||
);
|
||||
setState(() => loading = false);
|
||||
if (response == false ||
|
||||
!(response is Map) ||
|
||||
(response["results"] == null)) return;
|
||||
(response['results'] == null)) return;
|
||||
setState(() {
|
||||
foundProfiles = List<Map<String, dynamic>>.from(response["results"]);
|
||||
if ("@$text".isValidMatrixId &&
|
||||
foundProfiles = List<Map<String, dynamic>>.from(response['results']);
|
||||
if ('@$text'.isValidMatrixId &&
|
||||
foundProfiles
|
||||
.indexWhere((profile) => "@$text" == profile["user_id"]) ==
|
||||
.indexWhere((profile) => '@$text' == profile['user_id']) ==
|
||||
-1) {
|
||||
setState(() => foundProfiles = [
|
||||
{"user_id": "@$text"}
|
||||
{'user_id': '@$text'}
|
||||
]);
|
||||
}
|
||||
foundProfiles.removeWhere((profile) =>
|
||||
widget.room
|
||||
.getParticipants()
|
||||
.indexWhere((u) => u.id == profile["user_id"]) !=
|
||||
.indexWhere((u) => u.id == profile['user_id']) !=
|
||||
-1);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final String groupName = widget.room.name?.isEmpty ?? false
|
||||
final groupName = widget.room.name?.isEmpty ?? false
|
||||
? L10n.of(context).group
|
||||
: widget.room.name;
|
||||
return AdaptivePageLayout(
|
||||
|
|
@ -138,7 +139,7 @@ class _InvitationSelectionState extends State<InvitationSelection> {
|
|||
onSubmitted: (String text) => searchUser(context, text),
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(),
|
||||
prefixText: "@",
|
||||
prefixText: '@',
|
||||
hintText: L10n.of(context).username,
|
||||
labelText: L10n.of(context).inviteContactToGroup(groupName),
|
||||
suffixIcon: loading
|
||||
|
|
@ -159,19 +160,19 @@ class _InvitationSelectionState extends State<InvitationSelection> {
|
|||
itemCount: foundProfiles.length,
|
||||
itemBuilder: (BuildContext context, int i) => ListTile(
|
||||
leading: Avatar(
|
||||
foundProfiles[i]["avatar_url"] == null
|
||||
foundProfiles[i]['avatar_url'] == null
|
||||
? null
|
||||
: Uri.parse(foundProfiles[i]["avatar_url"]),
|
||||
foundProfiles[i]["display_name"] ??
|
||||
foundProfiles[i]["user_id"],
|
||||
: Uri.parse(foundProfiles[i]['avatar_url']),
|
||||
foundProfiles[i]['display_name'] ??
|
||||
foundProfiles[i]['user_id'],
|
||||
),
|
||||
title: Text(
|
||||
foundProfiles[i]["display_name"] ??
|
||||
(foundProfiles[i]["user_id"] as String).localpart,
|
||||
foundProfiles[i]['display_name'] ??
|
||||
(foundProfiles[i]['user_id'] as String).localpart,
|
||||
),
|
||||
subtitle: Text(foundProfiles[i]["user_id"]),
|
||||
subtitle: Text(foundProfiles[i]['user_id']),
|
||||
onTap: () =>
|
||||
inviteAction(context, foundProfiles[i]["user_id"]),
|
||||
inviteAction(context, foundProfiles[i]['user_id']),
|
||||
),
|
||||
)
|
||||
: FutureBuilder<List<User>>(
|
||||
|
|
@ -182,7 +183,7 @@ class _InvitationSelectionState extends State<InvitationSelection> {
|
|||
child: CircularProgressIndicator(),
|
||||
);
|
||||
}
|
||||
List<User> contacts = snapshot.data;
|
||||
var contacts = snapshot.data;
|
||||
return ListView.builder(
|
||||
itemCount: contacts.length,
|
||||
itemBuilder: (BuildContext context, int i) => ListTile(
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class _LoginState extends State<Login> {
|
|||
bool showPassword = false;
|
||||
|
||||
void login(BuildContext context) async {
|
||||
MatrixState matrix = Matrix.of(context);
|
||||
var matrix = Matrix.of(context);
|
||||
if (usernameController.text.isEmpty) {
|
||||
setState(() => usernameError = L10n.of(context).pleaseEnterYourUsername);
|
||||
} else {
|
||||
|
|
@ -101,7 +101,7 @@ class _LoginState extends State<Login> {
|
|||
controller: usernameController,
|
||||
decoration: InputDecoration(
|
||||
hintText:
|
||||
"@${L10n.of(context).username.toLowerCase()}:domain",
|
||||
'@${L10n.of(context).username.toLowerCase()}:domain',
|
||||
errorText: usernameError,
|
||||
labelText: L10n.of(context).username),
|
||||
),
|
||||
|
|
@ -120,7 +120,7 @@ class _LoginState extends State<Login> {
|
|||
obscureText: !showPassword,
|
||||
onSubmitted: (t) => login(context),
|
||||
decoration: InputDecoration(
|
||||
hintText: "****",
|
||||
hintText: '****',
|
||||
errorText: passwordError,
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(showPassword
|
||||
|
|
|
|||
|
|
@ -31,18 +31,18 @@ class _NewGroupState extends State<_NewGroup> {
|
|||
bool publicGroup = false;
|
||||
|
||||
void submitAction(BuildContext context) async {
|
||||
final MatrixState matrix = Matrix.of(context);
|
||||
Map<String, dynamic> params = {};
|
||||
final matrix = Matrix.of(context);
|
||||
var params = <String, dynamic>{};
|
||||
if (publicGroup) {
|
||||
params["preset"] = "public_chat";
|
||||
params["visibility"] = "public";
|
||||
params['preset'] = 'public_chat';
|
||||
params['visibility'] = 'public';
|
||||
if (controller.text.isNotEmpty) {
|
||||
params["room_alias_name"] = controller.text;
|
||||
params['room_alias_name'] = controller.text;
|
||||
}
|
||||
} else {
|
||||
params["preset"] = "private_chat";
|
||||
params['preset'] = 'private_chat';
|
||||
}
|
||||
if (controller.text.isNotEmpty) params["name"] = controller.text;
|
||||
if (controller.text.isNotEmpty) params['name'] = controller.text;
|
||||
final String roomID =
|
||||
await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
matrix.client.createRoom(params: params),
|
||||
|
|
@ -99,7 +99,7 @@ class _NewGroupState extends State<_NewGroup> {
|
|||
onChanged: (bool b) => setState(() => publicGroup = b),
|
||||
),
|
||||
Expanded(
|
||||
child: Image.asset("assets/new_group_wallpaper.png"),
|
||||
child: Image.asset('assets/new_group_wallpaper.png'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -37,23 +37,23 @@ class _NewPrivateChatState extends State<_NewPrivateChat> {
|
|||
List<Map<String, dynamic>> foundProfiles = [];
|
||||
Timer coolDown;
|
||||
Map<String, dynamic> get foundProfile => foundProfiles.firstWhere(
|
||||
(user) => user["user_id"] == "@$currentSearchTerm",
|
||||
(user) => user['user_id'] == '@$currentSearchTerm',
|
||||
orElse: () => null);
|
||||
bool get correctMxId =>
|
||||
foundProfiles
|
||||
.indexWhere((user) => user["user_id"] == "@$currentSearchTerm") !=
|
||||
.indexWhere((user) => user['user_id'] == '@$currentSearchTerm') !=
|
||||
-1;
|
||||
|
||||
void submitAction(BuildContext context) async {
|
||||
if (controller.text.isEmpty) return;
|
||||
if (!_formKey.currentState.validate()) return;
|
||||
final MatrixState matrix = Matrix.of(context);
|
||||
final matrix = Matrix.of(context);
|
||||
|
||||
if ("@" + controller.text.trim() == matrix.client.userID) return;
|
||||
if ('@' + controller.text.trim() == matrix.client.userID) return;
|
||||
|
||||
final User user = User(
|
||||
"@" + controller.text.trim(),
|
||||
room: Room(id: "", client: matrix.client),
|
||||
final user = User(
|
||||
'@' + controller.text.trim(),
|
||||
room: Room(id: '', client: matrix.client),
|
||||
);
|
||||
final String roomID = await SimpleDialogs(context)
|
||||
.tryRequestWithLoadingDialog(user.startDirectChat());
|
||||
|
|
@ -87,22 +87,22 @@ class _NewPrivateChatState extends State<_NewPrivateChat> {
|
|||
if (currentSearchTerm.isEmpty) return;
|
||||
if (loading) return;
|
||||
setState(() => loading = true);
|
||||
final MatrixState matrix = Matrix.of(context);
|
||||
final matrix = Matrix.of(context);
|
||||
final response = await SimpleDialogs(context).tryRequestWithErrorToast(
|
||||
matrix.client.jsonRequest(
|
||||
type: HTTPType.POST,
|
||||
action: "/client/r0/user_directory/search",
|
||||
action: '/client/r0/user_directory/search',
|
||||
data: {
|
||||
"search_term": text,
|
||||
"limit": 10,
|
||||
'search_term': text,
|
||||
'limit': 10,
|
||||
}),
|
||||
);
|
||||
setState(() => loading = false);
|
||||
if (response == false ||
|
||||
!(response is Map) ||
|
||||
(response["results"]?.isEmpty ?? true)) return;
|
||||
(response['results']?.isEmpty ?? true)) return;
|
||||
setState(() {
|
||||
foundProfiles = List<Map<String, dynamic>>.from(response["results"]);
|
||||
foundProfiles = List<Map<String, dynamic>>.from(response['results']);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -131,15 +131,15 @@ class _NewPrivateChatState extends State<_NewPrivateChat> {
|
|||
if (value.isEmpty) {
|
||||
return L10n.of(context).pleaseEnterAMatrixIdentifier;
|
||||
}
|
||||
final MatrixState matrix = Matrix.of(context);
|
||||
String mxid = "@" + controller.text.trim();
|
||||
final matrix = Matrix.of(context);
|
||||
var mxid = '@' + controller.text.trim();
|
||||
if (mxid == matrix.client.userID) {
|
||||
return L10n.of(context).youCannotInviteYourself;
|
||||
}
|
||||
if (!mxid.contains("@")) {
|
||||
if (!mxid.contains('@')) {
|
||||
return L10n.of(context).makeSureTheIdentifierIsValid;
|
||||
}
|
||||
if (!mxid.contains(":")) {
|
||||
if (!mxid.contains(':')) {
|
||||
return L10n.of(context).makeSureTheIdentifierIsValid;
|
||||
}
|
||||
return null;
|
||||
|
|
@ -158,17 +158,17 @@ class _NewPrivateChatState extends State<_NewPrivateChat> {
|
|||
? Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Avatar(
|
||||
foundProfile["avatar_url"] == null
|
||||
foundProfile['avatar_url'] == null
|
||||
? null
|
||||
: Uri.parse(foundProfile["avatar_url"]),
|
||||
foundProfile["display_name"] ??
|
||||
foundProfile["user_id"],
|
||||
: Uri.parse(foundProfile['avatar_url']),
|
||||
foundProfile['display_name'] ??
|
||||
foundProfile['user_id'],
|
||||
size: 12,
|
||||
),
|
||||
)
|
||||
: Icon(Icons.account_circle),
|
||||
prefixText: "@",
|
||||
hintText: "${L10n.of(context).username.toLowerCase()}",
|
||||
prefixText: '@',
|
||||
hintText: '${L10n.of(context).username.toLowerCase()}',
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -179,29 +179,29 @@ class _NewPrivateChatState extends State<_NewPrivateChat> {
|
|||
child: ListView.builder(
|
||||
itemCount: foundProfiles.length,
|
||||
itemBuilder: (BuildContext context, int i) {
|
||||
Map<String, dynamic> foundProfile = foundProfiles[i];
|
||||
var foundProfile = foundProfiles[i];
|
||||
return ListTile(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
controller.text = currentSearchTerm =
|
||||
foundProfile["user_id"].substring(1);
|
||||
foundProfile['user_id'].substring(1);
|
||||
});
|
||||
},
|
||||
leading: Avatar(
|
||||
foundProfile["avatar_url"] == null
|
||||
foundProfile['avatar_url'] == null
|
||||
? null
|
||||
: Uri.parse(foundProfile["avatar_url"]),
|
||||
foundProfile["display_name"] ?? foundProfile["user_id"],
|
||||
: Uri.parse(foundProfile['avatar_url']),
|
||||
foundProfile['display_name'] ?? foundProfile['user_id'],
|
||||
//size: 24,
|
||||
),
|
||||
title: Text(
|
||||
foundProfile["display_name"] ??
|
||||
(foundProfile["user_id"] as String).localpart,
|
||||
foundProfile['display_name'] ??
|
||||
(foundProfile['user_id'] as String).localpart,
|
||||
style: TextStyle(),
|
||||
maxLines: 1,
|
||||
),
|
||||
subtitle: Text(
|
||||
foundProfile["user_id"],
|
||||
foundProfile['user_id'],
|
||||
maxLines: 1,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
|
|
@ -219,9 +219,9 @@ class _NewPrivateChatState extends State<_NewPrivateChat> {
|
|||
),
|
||||
onTap: () => Share.share(L10n.of(context).inviteText(
|
||||
Matrix.of(context).client.userID,
|
||||
"https://matrix.to/#/${Matrix.of(context).client.userID}")),
|
||||
'https://matrix.to/#/${Matrix.of(context).client.userID}')),
|
||||
title: Text(
|
||||
"${L10n.of(context).yourOwnUsername}:",
|
||||
'${L10n.of(context).yourOwnUsername}:',
|
||||
style: TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
),
|
||||
|
|
@ -237,7 +237,7 @@ class _NewPrivateChatState extends State<_NewPrivateChat> {
|
|||
Divider(height: 1),
|
||||
if (foundProfiles.isEmpty || correctMxId)
|
||||
Expanded(
|
||||
child: Image.asset("assets/private_chat_wallpaper.png"),
|
||||
child: Image.asset('assets/private_chat_wallpaper.png'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:famedlysdk/famedlysdk.dart';
|
||||
import 'package:fluffychat/components/settings_themes.dart';
|
||||
import 'package:fluffychat/views/settings_devices.dart';
|
||||
|
|
@ -42,7 +40,7 @@ class _SettingsState extends State<Settings> {
|
|||
if (await SimpleDialogs(context).askConfirmation() == false) {
|
||||
return;
|
||||
}
|
||||
MatrixState matrix = Matrix.of(context);
|
||||
var matrix = Matrix.of(context);
|
||||
await SimpleDialogs(context)
|
||||
.tryRequestWithLoadingDialog(matrix.client.logout());
|
||||
}
|
||||
|
|
@ -57,20 +55,20 @@ class _SettingsState extends State<Settings> {
|
|||
if (!jitsi.endsWith('/')) {
|
||||
jitsi += '/';
|
||||
}
|
||||
final MatrixState matrix = Matrix.of(context);
|
||||
await matrix.client.storeAPI.setItem('chat.fluffy.jitsi_instance', jitsi);
|
||||
final matrix = Matrix.of(context);
|
||||
await matrix.store.setItem('chat.fluffy.jitsi_instance', jitsi);
|
||||
matrix.jitsiInstance = jitsi;
|
||||
}
|
||||
|
||||
void setDisplaynameAction(BuildContext context) async {
|
||||
final String displayname = await SimpleDialogs(context).enterText(
|
||||
final displayname = await SimpleDialogs(context).enterText(
|
||||
titleText: L10n.of(context).editDisplayname,
|
||||
hintText:
|
||||
profile?.displayname ?? Matrix.of(context).client.userID.localpart,
|
||||
labelText: L10n.of(context).enterAUsername,
|
||||
);
|
||||
if (displayname == null) return;
|
||||
final MatrixState matrix = Matrix.of(context);
|
||||
final matrix = Matrix.of(context);
|
||||
final success = await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
matrix.client.setDisplayname(displayname),
|
||||
);
|
||||
|
|
@ -83,13 +81,13 @@ class _SettingsState extends State<Settings> {
|
|||
}
|
||||
|
||||
void setAvatarAction(BuildContext context) async {
|
||||
final File tempFile = await ImagePicker.pickImage(
|
||||
final tempFile = await ImagePicker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
imageQuality: 50,
|
||||
maxWidth: 1600,
|
||||
maxHeight: 1600);
|
||||
if (tempFile == null) return;
|
||||
final MatrixState matrix = Matrix.of(context);
|
||||
final matrix = Matrix.of(context);
|
||||
final success = await SimpleDialogs(context).tryRequestWithLoadingDialog(
|
||||
matrix.client.setAvatar(
|
||||
MatrixFile(
|
||||
|
|
@ -111,24 +109,20 @@ class _SettingsState extends State<Settings> {
|
|||
if (wallpaper == null) return;
|
||||
Matrix.of(context).wallpaper = wallpaper;
|
||||
await Matrix.of(context)
|
||||
.client
|
||||
.storeAPI
|
||||
.setItem("chat.fluffy.wallpaper", wallpaper.path);
|
||||
.store
|
||||
.setItem('chat.fluffy.wallpaper', wallpaper.path);
|
||||
setState(() => null);
|
||||
}
|
||||
|
||||
void deleteWallpaperAction(BuildContext context) async {
|
||||
Matrix.of(context).wallpaper = null;
|
||||
await Matrix.of(context)
|
||||
.client
|
||||
.storeAPI
|
||||
.setItem("chat.fluffy.wallpaper", null);
|
||||
await Matrix.of(context).store.setItem('chat.fluffy.wallpaper', null);
|
||||
setState(() => null);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Client client = Matrix.of(context).client;
|
||||
final client = Matrix.of(context).client;
|
||||
profileFuture ??= client.ownProfile;
|
||||
profileFuture.then((p) {
|
||||
if (mounted) setState(() => profile = p);
|
||||
|
|
@ -174,8 +168,9 @@ class _SettingsState extends State<Settings> {
|
|||
),
|
||||
),
|
||||
ThemesSettings(),
|
||||
if (!kIsWeb && client.storeAPI != null) Divider(thickness: 1),
|
||||
if (!kIsWeb && client.storeAPI != null)
|
||||
if (!kIsWeb && Matrix.of(context).store != null)
|
||||
Divider(thickness: 1),
|
||||
if (!kIsWeb && Matrix.of(context).store != null)
|
||||
ListTile(
|
||||
title: Text(
|
||||
L10n.of(context).wallpaper,
|
||||
|
|
@ -198,7 +193,7 @@ class _SettingsState extends State<Settings> {
|
|||
),
|
||||
onTap: () => deleteWallpaperAction(context),
|
||||
),
|
||||
if (!kIsWeb && client.storeAPI != null)
|
||||
if (!kIsWeb && Matrix.of(context).store != null)
|
||||
Builder(builder: (context) {
|
||||
return ListTile(
|
||||
title: Text(L10n.of(context).changeWallpaper),
|
||||
|
|
@ -223,8 +218,9 @@ class _SettingsState extends State<Settings> {
|
|||
activeColor: Theme.of(context).primaryColor,
|
||||
onChanged: (bool newValue) async {
|
||||
Matrix.of(context).renderHtml = newValue;
|
||||
await client.storeAPI
|
||||
.setItem("chat.fluffy.renderHtml", newValue ? "1" : "0");
|
||||
await Matrix.of(context)
|
||||
.store
|
||||
.setItem('chat.fluffy.renderHtml', newValue ? '1' : '0');
|
||||
setState(() => null);
|
||||
},
|
||||
),
|
||||
|
|
@ -300,19 +296,19 @@ class _SettingsState extends State<Settings> {
|
|||
trailing: Icon(Icons.help),
|
||||
title: Text(L10n.of(context).help),
|
||||
onTap: () => launch(
|
||||
"https://gitlab.com/ChristianPauly/fluffychat-flutter/issues"),
|
||||
'https://gitlab.com/ChristianPauly/fluffychat-flutter/issues'),
|
||||
),
|
||||
ListTile(
|
||||
trailing: Icon(Icons.link),
|
||||
title: Text(L10n.of(context).license),
|
||||
onTap: () => launch(
|
||||
"https://gitlab.com/ChristianPauly/fluffychat-flutter/raw/master/LICENSE"),
|
||||
'https://gitlab.com/ChristianPauly/fluffychat-flutter/raw/master/LICENSE'),
|
||||
),
|
||||
ListTile(
|
||||
trailing: Icon(Icons.code),
|
||||
title: Text(L10n.of(context).sourceCode),
|
||||
onTap: () => launch(
|
||||
"https://gitlab.com/ChristianPauly/fluffychat-flutter"),
|
||||
'https://gitlab.com/ChristianPauly/fluffychat-flutter'),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
|
|||
|
|
@ -37,18 +37,18 @@ class DevicesSettingsState extends State<DevicesSettings> {
|
|||
void _removeDevicesAction(
|
||||
BuildContext context, List<UserDevice> devices) async {
|
||||
if (await SimpleDialogs(context).askConfirmation() == false) return;
|
||||
MatrixState matrix = Matrix.of(context);
|
||||
List<String> deviceIds = [];
|
||||
for (UserDevice userDevice in devices) {
|
||||
var matrix = Matrix.of(context);
|
||||
var deviceIds = <String>[];
|
||||
for (var userDevice in devices) {
|
||||
deviceIds.add(userDevice.deviceId);
|
||||
}
|
||||
final success = await SimpleDialogs(context)
|
||||
.tryRequestWithLoadingDialog(matrix.client.deleteDevices(deviceIds),
|
||||
onAdditionalAuth: (MatrixException exception) async {
|
||||
final String password = await SimpleDialogs(context).enterText(
|
||||
final password = await SimpleDialogs(context).enterText(
|
||||
titleText: L10n.of(context).pleaseEnterYourPassword,
|
||||
labelText: L10n.of(context).pleaseEnterYourPassword,
|
||||
hintText: "******",
|
||||
hintText: '******',
|
||||
password: true);
|
||||
if (password == null) return;
|
||||
await matrix.client.deleteDevices(deviceIds,
|
||||
|
|
@ -83,9 +83,8 @@ class DevicesSettingsState extends State<DevicesSettings> {
|
|||
}
|
||||
Function isOwnDevice = (UserDevice userDevice) =>
|
||||
userDevice.deviceId == Matrix.of(context).client.deviceID;
|
||||
final List<UserDevice> devices = List<UserDevice>.from(this.devices);
|
||||
UserDevice thisDevice =
|
||||
devices.firstWhere(isOwnDevice, orElse: () => null);
|
||||
final devices = List<UserDevice>.from(this.devices);
|
||||
var thisDevice = devices.firstWhere(isOwnDevice, orElse: () => null);
|
||||
devices.removeWhere(isOwnDevice);
|
||||
devices.sort((a, b) => b.lastSeenTs.compareTo(a.lastSeenTs));
|
||||
return Column(
|
||||
|
|
@ -145,13 +144,13 @@ class UserDeviceListItem extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return PopupMenuButton(
|
||||
onSelected: (String action) {
|
||||
if (action == "remove" && this.remove != null) {
|
||||
if (action == 'remove' && remove != null) {
|
||||
remove(userDevice);
|
||||
}
|
||||
},
|
||||
itemBuilder: (BuildContext context) => [
|
||||
PopupMenuItem<String>(
|
||||
value: "remove",
|
||||
value: 'remove',
|
||||
child: Text(L10n.of(context).removeDevice,
|
||||
style: TextStyle(color: Colors.red)),
|
||||
),
|
||||
|
|
@ -175,8 +174,8 @@ class UserDeviceListItem extends StatelessWidget {
|
|||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text("${L10n.of(context).id}: ${userDevice.deviceId}"),
|
||||
Text("${L10n.of(context).lastSeenIp}: ${userDevice.lastSeenIp}"),
|
||||
Text('${L10n.of(context).id}: ${userDevice.deviceId}'),
|
||||
Text('${L10n.of(context).lastSeenIp}: ${userDevice.lastSeenIp}'),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_advanced_networkimage/provider.dart';
|
||||
|
|
@ -55,7 +53,7 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
|||
if (readonly) {
|
||||
return;
|
||||
}
|
||||
debugPrint("Saving....");
|
||||
debugPrint('Saving....');
|
||||
final client = Matrix.of(context).client;
|
||||
// be sure to preserve any data not in "short"
|
||||
Map<String, dynamic> content;
|
||||
|
|
@ -95,7 +93,7 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Client client = Matrix.of(context).client;
|
||||
var client = Matrix.of(context).client;
|
||||
if (emotes == null) {
|
||||
emotes = <_EmoteEntry>[];
|
||||
Map<String, dynamic> emoteSource;
|
||||
|
|
@ -173,7 +171,7 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
|||
size: 32.0,
|
||||
),
|
||||
onTap: () async {
|
||||
debugPrint("blah");
|
||||
debugPrint('blah');
|
||||
if (newEmoteController.text == null ||
|
||||
newEmoteController.text.isEmpty ||
|
||||
newMxcController.text == null ||
|
||||
|
|
@ -374,7 +372,7 @@ class _EmoteImagePickerState extends State<_EmoteImagePicker> {
|
|||
BotToast.showText(text: L10n.of(context).notSupportedInWeb);
|
||||
return;
|
||||
}
|
||||
File file = await ImagePicker.pickImage(
|
||||
var file = await ImagePicker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
imageQuality: 50,
|
||||
maxWidth: 128,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class _SignUpState extends State<SignUp> {
|
|||
File avatar;
|
||||
|
||||
void setAvatarAction() async {
|
||||
File file = await ImagePicker.pickImage(
|
||||
var file = await ImagePicker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
maxHeight: 512,
|
||||
maxWidth: 512,
|
||||
|
|
@ -33,7 +33,7 @@ class _SignUpState extends State<SignUp> {
|
|||
}
|
||||
|
||||
void signUpAction(BuildContext context) async {
|
||||
MatrixState matrix = Matrix.of(context);
|
||||
var matrix = Matrix.of(context);
|
||||
if (usernameController.text.isEmpty) {
|
||||
setState(() => usernameError = L10n.of(context).pleaseChooseAUsername);
|
||||
} else {
|
||||
|
|
@ -45,8 +45,8 @@ class _SignUpState extends State<SignUp> {
|
|||
}
|
||||
setState(() => loading = true);
|
||||
|
||||
final String preferredUsername =
|
||||
usernameController.text.toLowerCase().replaceAll(" ", "-");
|
||||
final preferredUsername =
|
||||
usernameController.text.toLowerCase().replaceAll(' ', '-');
|
||||
|
||||
try {
|
||||
await matrix.client.usernameAvailable(preferredUsername);
|
||||
|
|
@ -83,7 +83,7 @@ class _SignUpState extends State<SignUp> {
|
|||
children: <Widget>[
|
||||
Hero(
|
||||
tag: 'loginBanner',
|
||||
child: Image.asset("assets/fluffychat-banner.png"),
|
||||
child: Image.asset('assets/fluffychat-banner.png'),
|
||||
),
|
||||
ListTile(
|
||||
leading: CircleAvatar(
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class _SignUpPasswordState extends State<SignUpPassword> {
|
|||
bool showPassword = true;
|
||||
|
||||
void _signUpAction(BuildContext context, {Map<String, dynamic> auth}) async {
|
||||
MatrixState matrix = Matrix.of(context);
|
||||
var matrix = Matrix.of(context);
|
||||
if (passwordController.text.isEmpty) {
|
||||
setState(() => passwordError = L10n.of(context).pleaseEnterYourPassword);
|
||||
} else {
|
||||
|
|
@ -40,8 +40,7 @@ class _SignUpPasswordState extends State<SignUpPassword> {
|
|||
|
||||
try {
|
||||
setState(() => loading = true);
|
||||
Future<LoginState> waitForLogin =
|
||||
matrix.client.onLoginStateChanged.stream.first;
|
||||
var waitForLogin = matrix.client.onLoginStateChanged.stream.first;
|
||||
await matrix.client.register(
|
||||
username: widget.username,
|
||||
password: passwordController.text,
|
||||
|
|
@ -51,21 +50,20 @@ class _SignUpPasswordState extends State<SignUpPassword> {
|
|||
await waitForLogin;
|
||||
} on MatrixException catch (exception) {
|
||||
if (exception.requireAdditionalAuthentication) {
|
||||
final List<String> stages = exception.authenticationFlows
|
||||
.firstWhere((a) => !a.stages.contains("m.login.email.identity"))
|
||||
final stages = exception.authenticationFlows
|
||||
.firstWhere((a) => !a.stages.contains('m.login.email.identity'))
|
||||
.stages;
|
||||
|
||||
final String currentStage =
|
||||
exception.completedAuthenticationFlows == null
|
||||
? stages.first
|
||||
: stages.firstWhere((stage) =>
|
||||
!exception.completedAuthenticationFlows.contains(stage) ??
|
||||
true);
|
||||
final currentStage = exception.completedAuthenticationFlows == null
|
||||
? stages.first
|
||||
: stages.firstWhere((stage) =>
|
||||
!exception.completedAuthenticationFlows.contains(stage) ??
|
||||
true);
|
||||
|
||||
if (currentStage == "m.login.dummy") {
|
||||
if (currentStage == 'm.login.dummy') {
|
||||
_signUpAction(context, auth: {
|
||||
"type": currentStage,
|
||||
"session": exception.session,
|
||||
'type': currentStage,
|
||||
'session': exception.session,
|
||||
});
|
||||
} else {
|
||||
await Navigator.of(context).push(
|
||||
|
|
@ -75,7 +73,7 @@ class _SignUpPasswordState extends State<SignUpPassword> {
|
|||
currentStage,
|
||||
exception.session,
|
||||
() => _signUpAction(context, auth: {
|
||||
"session": exception.session,
|
||||
'session': exception.session,
|
||||
}),
|
||||
),
|
||||
),
|
||||
|
|
@ -141,7 +139,7 @@ class _SignUpPasswordState extends State<SignUpPassword> {
|
|||
autocorrect: false,
|
||||
onSubmitted: (t) => _signUpAction(context),
|
||||
decoration: InputDecoration(
|
||||
hintText: "****",
|
||||
hintText: '****',
|
||||
errorText: passwordError,
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue