mirror of
https://gitlab.com/famedly/fluffychat.git
synced 2024-12-24 22:42:33 +01:00
refactor: Migrate to flutter 2
This commit is contained in:
parent
a553c049d7
commit
bb97b1bca8
@ -25,7 +25,6 @@ test:
|
|||||||
|
|
||||||
build_web:
|
build_web:
|
||||||
stage: coverage
|
stage: coverage
|
||||||
image: registry.gitlab.com/famedly/containers/flutter-dockerimages:beta
|
|
||||||
before_script: [sudo apt update && sudo apt install curl -y, ./scripts/prepare-web.sh]
|
before_script: [sudo apt update && sudo apt install curl -y, ./scripts/prepare-web.sh]
|
||||||
script: [./scripts/build-web.sh]
|
script: [./scripts/build-web.sh]
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -157,7 +156,6 @@ pages:
|
|||||||
|
|
||||||
build_linux:
|
build_linux:
|
||||||
stage: coverage
|
stage: coverage
|
||||||
image: cirrusci/flutter:dev
|
|
||||||
before_script: [sudo apt update && sudo apt install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev -y]
|
before_script: [sudo apt update && sudo apt install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev -y]
|
||||||
script: [./scripts/build-linux.sh]
|
script: [./scripts/build-linux.sh]
|
||||||
artifacts:
|
artifacts:
|
||||||
@ -260,7 +258,6 @@ upload-windows:
|
|||||||
|
|
||||||
upload-playstore:
|
upload-playstore:
|
||||||
extends: .release
|
extends: .release
|
||||||
image: registry.gitlab.com/famedly/containers/flutter-dockerimages:stable
|
|
||||||
script: [./scripts/release-playstore.sh]
|
script: [./scripts/release-playstore.sh]
|
||||||
resource_group: playstore_release
|
resource_group: playstore_release
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ class ContentBanner extends StatelessWidget {
|
|||||||
alignment: Alignment.bottomRight,
|
alignment: Alignment.bottomRight,
|
||||||
child: FloatingActionButton(
|
child: FloatingActionButton(
|
||||||
mini: true,
|
mini: true,
|
||||||
child: Icon(Icons.camera_alt_outlined),
|
|
||||||
onPressed: onEdit,
|
onPressed: onEdit,
|
||||||
|
child: Icon(Icons.camera_alt_outlined),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -18,17 +18,17 @@ class AdaptiveFlatButton extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (PlatformInfos.isCupertinoStyle) {
|
if (PlatformInfos.isCupertinoStyle) {
|
||||||
return CupertinoDialogAction(
|
return CupertinoDialogAction(
|
||||||
child: Text(label),
|
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
textStyle: textColor != null ? TextStyle(color: textColor) : null,
|
textStyle: textColor != null ? TextStyle(color: textColor) : null,
|
||||||
|
child: Text(label),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return TextButton(
|
return TextButton(
|
||||||
|
onPressed: onPressed,
|
||||||
child: Text(
|
child: Text(
|
||||||
label,
|
label,
|
||||||
style: TextStyle(color: textColor),
|
style: TextStyle(color: textColor),
|
||||||
),
|
),
|
||||||
onPressed: onPressed,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,7 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
body = Container(
|
body = Container(
|
||||||
margin: EdgeInsets.only(left: 8.0, right: 8.0),
|
margin: EdgeInsets.only(left: 8.0, right: 8.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(L10n.of(context).askSSSSSign,
|
Text(L10n.of(context).askSSSSSign,
|
||||||
style: TextStyle(fontSize: 20)),
|
style: TextStyle(fontSize: 20)),
|
||||||
@ -128,7 +129,6 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
buttons.add(AdaptiveFlatButton(
|
buttons.add(AdaptiveFlatButton(
|
||||||
@ -145,10 +145,10 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
break;
|
break;
|
||||||
case KeyVerificationState.askAccept:
|
case KeyVerificationState.askAccept:
|
||||||
body = Container(
|
body = Container(
|
||||||
|
margin: EdgeInsets.only(left: 8.0, right: 8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).askVerificationRequest(widget.request.userId),
|
L10n.of(context).askVerificationRequest(widget.request.userId),
|
||||||
style: TextStyle(fontSize: 20)),
|
style: TextStyle(fontSize: 20)),
|
||||||
margin: EdgeInsets.only(left: 8.0, right: 8.0),
|
|
||||||
);
|
);
|
||||||
buttons.add(AdaptiveFlatButton(
|
buttons.add(AdaptiveFlatButton(
|
||||||
label: L10n.of(context).accept,
|
label: L10n.of(context).accept,
|
||||||
@ -165,6 +165,7 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
break;
|
break;
|
||||||
case KeyVerificationState.waitingAccept:
|
case KeyVerificationState.waitingAccept:
|
||||||
body = Column(
|
body = Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
PlatformInfos.isCupertinoStyle
|
PlatformInfos.isCupertinoStyle
|
||||||
? CupertinoActivityIndicator()
|
? CupertinoActivityIndicator()
|
||||||
@ -175,7 +176,6 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
);
|
);
|
||||||
final key = widget.request.client.userDeviceKeys[widget.request.userId]
|
final key = widget.request.client.userDeviceKeys[widget.request.userId]
|
||||||
.deviceKeys[widget.request.deviceId];
|
.deviceKeys[widget.request.deviceId];
|
||||||
@ -219,6 +219,7 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
TextSpan(text: numbstr, style: TextStyle(fontSize: 40));
|
TextSpan(text: numbstr, style: TextStyle(fontSize: 40));
|
||||||
}
|
}
|
||||||
body = Column(
|
body = Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Center(
|
Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
@ -233,7 +234,6 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
);
|
);
|
||||||
buttons.add(AdaptiveFlatButton(
|
buttons.add(AdaptiveFlatButton(
|
||||||
textColor: Colors.red,
|
textColor: Colors.red,
|
||||||
@ -250,6 +250,7 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
? L10n.of(context).waitingPartnerEmoji
|
? L10n.of(context).waitingPartnerEmoji
|
||||||
: L10n.of(context).waitingPartnerNumbers;
|
: L10n.of(context).waitingPartnerNumbers;
|
||||||
body = Column(
|
body = Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
PlatformInfos.isCupertinoStyle
|
PlatformInfos.isCupertinoStyle
|
||||||
? CupertinoActivityIndicator()
|
? CupertinoActivityIndicator()
|
||||||
@ -260,11 +261,11 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case KeyVerificationState.done:
|
case KeyVerificationState.done:
|
||||||
body = Column(
|
body = Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Icon(Icons.check_circle_outlined, color: Colors.green, size: 200.0),
|
Icon(Icons.check_circle_outlined, color: Colors.green, size: 200.0),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
@ -273,7 +274,6 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
);
|
);
|
||||||
buttons.add(AdaptiveFlatButton(
|
buttons.add(AdaptiveFlatButton(
|
||||||
label: L10n.of(context).close,
|
label: L10n.of(context).close,
|
||||||
@ -282,6 +282,7 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
break;
|
break;
|
||||||
case KeyVerificationState.error:
|
case KeyVerificationState.error:
|
||||||
body = Column(
|
body = Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Icon(Icons.cancel, color: Colors.red, size: 200.0),
|
Icon(Icons.cancel, color: Colors.red, size: 200.0),
|
||||||
SizedBox(height: 10),
|
SizedBox(height: 10),
|
||||||
@ -290,7 +291,6 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
);
|
);
|
||||||
buttons.add(AdaptiveFlatButton(
|
buttons.add(AdaptiveFlatButton(
|
||||||
label: L10n.of(context).close,
|
label: L10n.of(context).close,
|
||||||
@ -318,6 +318,7 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
}
|
}
|
||||||
final userNameTitle = Row(
|
final userNameTitle = Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
otherName,
|
otherName,
|
||||||
@ -336,7 +337,6 @@ class _KeyVerificationPageState extends State<KeyVerificationDialog> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
);
|
);
|
||||||
final title = Text(L10n.of(context).verifyTitle);
|
final title = Text(L10n.of(context).verifyTitle);
|
||||||
final content = Scrollbar(
|
final content = Scrollbar(
|
||||||
|
@ -108,15 +108,21 @@ class _RecordingDialogState extends State<RecordingDialog> {
|
|||||||
),
|
),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
TextButton(
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context, rootNavigator: false).pop(),
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).cancel.toUpperCase(),
|
L10n.of(context).cancel.toUpperCase(),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).textTheme.bodyText2.color.withAlpha(150),
|
color: Theme.of(context).textTheme.bodyText2.color.withAlpha(150),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => Navigator.of(context, rootNavigator: false).pop(),
|
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await _recorderSubscription?.cancel();
|
||||||
|
await flutterSound.stopRecorder();
|
||||||
|
Navigator.of(context, rootNavigator: false)
|
||||||
|
.pop<String>(_recordedPath);
|
||||||
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(L10n.of(context).send.toUpperCase()),
|
Text(L10n.of(context).send.toUpperCase()),
|
||||||
@ -124,12 +130,6 @@ class _RecordingDialogState extends State<RecordingDialog> {
|
|||||||
Icon(Icons.send_outlined, size: 15),
|
Icon(Icons.send_outlined, size: 15),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
|
||||||
await _recorderSubscription?.cancel();
|
|
||||||
await flutterSound.stopRecorder();
|
|
||||||
Navigator.of(context, rootNavigator: false)
|
|
||||||
.pop<String>(_recordedPath);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -78,14 +78,13 @@ class _SendFileDialogState extends State<SendFileDialog> {
|
|||||||
content: contentWidget,
|
content: contentWidget,
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(L10n.of(context).cancel),
|
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
// just close the dialog
|
// just close the dialog
|
||||||
Navigator.of(context, rootNavigator: false).pop();
|
Navigator.of(context, rootNavigator: false).pop();
|
||||||
},
|
},
|
||||||
|
child: Text(L10n.of(context).cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(L10n.of(context).send),
|
|
||||||
onPressed: _isSending
|
onPressed: _isSending
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () async {
|
||||||
@ -94,8 +93,9 @@ class _SendFileDialogState extends State<SendFileDialog> {
|
|||||||
});
|
});
|
||||||
await showFutureLoadingDialog(
|
await showFutureLoadingDialog(
|
||||||
context: context, future: () => _send());
|
context: context, future: () => _send());
|
||||||
await Navigator.of(context, rootNavigator: false).pop();
|
Navigator.of(context, rootNavigator: false).pop();
|
||||||
},
|
},
|
||||||
|
child: Text(L10n.of(context).send),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -231,25 +231,25 @@ class InputBar extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
insertText = (isUnique
|
insertText = (isUnique
|
||||||
? insertEmote
|
? insertEmote
|
||||||
: ':${insertPack}~${insertEmote.substring(1)}') +
|
: ':$insertPack~${insertEmote.substring(1)}') +
|
||||||
' ';
|
' ';
|
||||||
startText = replaceText.replaceAllMapped(
|
startText = replaceText.replaceAllMapped(
|
||||||
RegExp(r'(\s|^)(:(?:[-\w]+~)?[-\w]+)$'),
|
RegExp(r'(\s|^)(:(?:[-\w]+~)?[-\w]+)$'),
|
||||||
(Match m) => '${m[1]}${insertText}',
|
(Match m) => '${m[1]}$insertText',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (suggestion['type'] == 'user') {
|
if (suggestion['type'] == 'user') {
|
||||||
insertText = suggestion['mxid'] + ' ';
|
insertText = suggestion['mxid'] + ' ';
|
||||||
startText = replaceText.replaceAllMapped(
|
startText = replaceText.replaceAllMapped(
|
||||||
RegExp(r'(\s|^)(@[-\w]+)$'),
|
RegExp(r'(\s|^)(@[-\w]+)$'),
|
||||||
(Match m) => '${m[1]}${insertText}',
|
(Match m) => '${m[1]}$insertText',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (suggestion['type'] == 'room') {
|
if (suggestion['type'] == 'room') {
|
||||||
insertText = suggestion['mxid'] + ' ';
|
insertText = suggestion['mxid'] + ' ';
|
||||||
startText = replaceText.replaceAllMapped(
|
startText = replaceText.replaceAllMapped(
|
||||||
RegExp(r'(\s|^)(#[-\w]+)$'),
|
RegExp(r'(\s|^)(#[-\w]+)$'),
|
||||||
(Match m) => '${m[1]}${insertText}',
|
(Match m) => '${m[1]}$insertText',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (insertText.isNotEmpty && startText.isNotEmpty) {
|
if (insertText.isNotEmpty && startText.isNotEmpty) {
|
||||||
|
@ -109,6 +109,11 @@ class Message extends StatelessWidget {
|
|||||||
originServerTs: DateTime.now(),
|
originServerTs: DateTime.now(),
|
||||||
);
|
);
|
||||||
return InkWell(
|
return InkWell(
|
||||||
|
onTap: () {
|
||||||
|
if (scrollToEventId != null) {
|
||||||
|
scrollToEventId(replyEvent.eventId);
|
||||||
|
}
|
||||||
|
},
|
||||||
child: AbsorbPointer(
|
child: AbsorbPointer(
|
||||||
child: Container(
|
child: Container(
|
||||||
margin: EdgeInsets.symmetric(vertical: 4.0),
|
margin: EdgeInsets.symmetric(vertical: 4.0),
|
||||||
@ -116,11 +121,6 @@ class Message extends StatelessWidget {
|
|||||||
lightText: ownMessage, timeline: timeline),
|
lightText: ownMessage, timeline: timeline),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () {
|
|
||||||
if (scrollToEventId != null) {
|
|
||||||
scrollToEventId(replyEvent.eventId);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -123,42 +123,28 @@ class MessageContent extends StatelessWidget {
|
|||||||
continue textmessage;
|
continue textmessage;
|
||||||
case MessageTypes.BadEncrypted:
|
case MessageTypes.BadEncrypted:
|
||||||
case EventTypes.Encrypted:
|
case EventTypes.Encrypted:
|
||||||
return RaisedButton(
|
return ElevatedButton.icon(
|
||||||
elevation: 7,
|
style: ElevatedButton.styleFrom(
|
||||||
color: Theme.of(context).scaffoldBackgroundColor,
|
primary: Theme.of(context).scaffoldBackgroundColor,
|
||||||
shape: RoundedRectangleBorder(
|
onPrimary: Theme.of(context).textTheme.bodyText1.color,
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(Icons.lock_outline),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Text(L10n.of(context).encrypted),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
onPressed: () => _verifyOrRequestKey(context),
|
onPressed: () => _verifyOrRequestKey(context),
|
||||||
|
icon: Icon(Icons.lock_outline),
|
||||||
|
label: Text(L10n.of(context).encrypted),
|
||||||
);
|
);
|
||||||
case MessageTypes.Location:
|
case MessageTypes.Location:
|
||||||
case MessageTypes.None:
|
case MessageTypes.None:
|
||||||
textmessage:
|
textmessage:
|
||||||
default:
|
default:
|
||||||
if (event.content['msgtype'] == Matrix.callNamespace) {
|
if (event.content['msgtype'] == Matrix.callNamespace) {
|
||||||
return RaisedButton(
|
return ElevatedButton.icon(
|
||||||
elevation: 7,
|
style: ElevatedButton.styleFrom(
|
||||||
color: Theme.of(context).scaffoldBackgroundColor,
|
primary: Theme.of(context).scaffoldBackgroundColor,
|
||||||
shape: RoundedRectangleBorder(
|
onPrimary: Theme.of(context).textTheme.bodyText1.color,
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: <Widget>[
|
|
||||||
Icon(Icons.phone_outlined, color: Colors.green),
|
|
||||||
SizedBox(width: 8),
|
|
||||||
Text(L10n.of(context).videoCall),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
onPressed: () => launch(event.body),
|
onPressed: () => launch(event.body),
|
||||||
|
icon: Icon(Icons.phone_outlined, color: Colors.green),
|
||||||
|
label: Text(L10n.of(context).videoCall),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (event.redacted) {
|
if (event.redacted) {
|
||||||
|
@ -19,12 +19,12 @@ class MessageDownloadContent extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
RaisedButton(
|
ElevatedButton(
|
||||||
elevation: 7,
|
style: ElevatedButton.styleFrom(
|
||||||
color: Theme.of(context).scaffoldBackgroundColor,
|
primary: Theme.of(context).scaffoldBackgroundColor,
|
||||||
shape: RoundedRectangleBorder(
|
onPrimary: Theme.of(context).textTheme.bodyText1.color,
|
||||||
borderRadius: BorderRadius.circular(6),
|
|
||||||
),
|
),
|
||||||
|
onPressed: () => event.openFile(context),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@ -38,7 +38,6 @@ class MessageDownloadContent extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onPressed: () => event.openFile(context),
|
|
||||||
),
|
),
|
||||||
if (event.sizeString != null)
|
if (event.sizeString != null)
|
||||||
Text(
|
Text(
|
||||||
|
@ -120,6 +120,7 @@ class _Reaction extends StatelessWidget {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
return InkWell(
|
return InkWell(
|
||||||
|
onTap: () => onTap != null ? onTap() : null,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: color,
|
color: color,
|
||||||
@ -132,7 +133,6 @@ class _Reaction extends StatelessWidget {
|
|||||||
padding: EdgeInsets.all(padding),
|
padding: EdgeInsets.all(padding),
|
||||||
child: content,
|
child: content,
|
||||||
),
|
),
|
||||||
onTap: () => onTap != null ? onTap() : null,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ class UserBottomSheet extends StatelessWidget {
|
|||||||
case 'message':
|
case 'message':
|
||||||
final roomId = await user.startDirectChat();
|
final roomId = await user.startDirectChat();
|
||||||
await AdaptivePageLayout.of(context)
|
await AdaptivePageLayout.of(context)
|
||||||
.pushNamedAndRemoveUntilIsFirst('/rooms/${roomId}');
|
.pushNamedAndRemoveUntilIsFirst('/rooms/$roomId');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,60 +95,66 @@ class UserBottomSheet extends StatelessWidget {
|
|||||||
if (onMention != null) {
|
if (onMention != null) {
|
||||||
items.add(
|
items.add(
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
value: 'mention',
|
||||||
child: _TextWithIcon(
|
child: _TextWithIcon(
|
||||||
L10n.of(context).mention,
|
L10n.of(context).mention,
|
||||||
Icons.alternate_email_outlined,
|
Icons.alternate_email_outlined,
|
||||||
),
|
),
|
||||||
value: 'mention'),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (user.id != user.room.client.userID && !user.room.isDirectChat) {
|
if (user.id != user.room.client.userID && !user.room.isDirectChat) {
|
||||||
items.add(
|
items.add(
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
value: 'message',
|
||||||
child: _TextWithIcon(
|
child: _TextWithIcon(
|
||||||
L10n.of(context).sendAMessage,
|
L10n.of(context).sendAMessage,
|
||||||
Icons.send_outlined,
|
Icons.send_outlined,
|
||||||
),
|
),
|
||||||
value: 'message'),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (user.canChangePowerLevel) {
|
if (user.canChangePowerLevel) {
|
||||||
items.add(
|
items.add(
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
value: 'permission',
|
||||||
child: _TextWithIcon(
|
child: _TextWithIcon(
|
||||||
L10n.of(context).setPermissionsLevel,
|
L10n.of(context).setPermissionsLevel,
|
||||||
Icons.edit_attributes_outlined,
|
Icons.edit_attributes_outlined,
|
||||||
),
|
),
|
||||||
value: 'permission'),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (user.canKick) {
|
if (user.canKick) {
|
||||||
items.add(
|
items.add(
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
value: 'kick',
|
||||||
child: _TextWithIcon(
|
child: _TextWithIcon(
|
||||||
L10n.of(context).kickFromChat,
|
L10n.of(context).kickFromChat,
|
||||||
Icons.exit_to_app_outlined,
|
Icons.exit_to_app_outlined,
|
||||||
),
|
),
|
||||||
value: 'kick'),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (user.canBan && user.membership != Membership.ban) {
|
if (user.canBan && user.membership != Membership.ban) {
|
||||||
items.add(
|
items.add(
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
value: 'ban',
|
||||||
child: _TextWithIcon(
|
child: _TextWithIcon(
|
||||||
L10n.of(context).banFromChat,
|
L10n.of(context).banFromChat,
|
||||||
Icons.warning_sharp,
|
Icons.warning_sharp,
|
||||||
),
|
),
|
||||||
value: 'ban'),
|
),
|
||||||
);
|
);
|
||||||
} else if (user.canBan && user.membership == Membership.ban) {
|
} else if (user.canBan && user.membership == Membership.ban) {
|
||||||
items.add(
|
items.add(
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
value: 'unban',
|
||||||
child: _TextWithIcon(
|
child: _TextWithIcon(
|
||||||
L10n.of(context).removeExile,
|
L10n.of(context).removeExile,
|
||||||
Icons.warning_outlined,
|
Icons.warning_outlined,
|
||||||
),
|
),
|
||||||
value: 'unban'),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return Center(
|
return Center(
|
||||||
|
@ -28,6 +28,7 @@ abstract class FluffyThemes {
|
|||||||
: TextTheme();
|
: TextTheme();
|
||||||
|
|
||||||
static ThemeData light = ThemeData(
|
static ThemeData light = ThemeData(
|
||||||
|
visualDensity: VisualDensity.standard,
|
||||||
primaryColorDark: Colors.white,
|
primaryColorDark: Colors.white,
|
||||||
primaryColorLight: Color(0xff121212),
|
primaryColorLight: Color(0xff121212),
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
@ -54,6 +55,17 @@ abstract class FluffyThemes {
|
|||||||
backgroundColor: AppConfig.primaryColor,
|
backgroundColor: AppConfig.primaryColor,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
),
|
),
|
||||||
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
primary: AppConfig.primaryColor,
|
||||||
|
onPrimary: Colors.white,
|
||||||
|
elevation: 7,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.all(12),
|
||||||
|
),
|
||||||
|
),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius)),
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius)),
|
||||||
@ -80,6 +92,7 @@ abstract class FluffyThemes {
|
|||||||
);
|
);
|
||||||
|
|
||||||
static ThemeData dark = ThemeData.dark().copyWith(
|
static ThemeData dark = ThemeData.dark().copyWith(
|
||||||
|
visualDensity: VisualDensity.standard,
|
||||||
primaryColorDark: Color(0xff121212),
|
primaryColorDark: Color(0xff121212),
|
||||||
primaryColorLight: Colors.white,
|
primaryColorLight: Colors.white,
|
||||||
primaryColor: AppConfig.primaryColor,
|
primaryColor: AppConfig.primaryColor,
|
||||||
|
@ -13,5 +13,5 @@ Future<Database> constructDb(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getLocalstorage(String key) async {
|
Future<String> getLocalstorage(String key) async {
|
||||||
return await window.localStorage[key];
|
return window.localStorage[key];
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ class Store {
|
|||||||
if (!PlatformInfos.isMobile) {
|
if (!PlatformInfos.isMobile) {
|
||||||
await _setupLocalStorage();
|
await _setupLocalStorage();
|
||||||
try {
|
try {
|
||||||
return await storage.getItem(key)?.toString();
|
return storage.getItem(key)?.toString();
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,13 @@ abstract class PlatformInfos {
|
|||||||
useRootNavigator: false,
|
useRootNavigator: false,
|
||||||
children: [
|
children: [
|
||||||
Text('Version: $version'),
|
Text('Version: $version'),
|
||||||
RaisedButton(
|
OutlinedButton(
|
||||||
child: Text(L10n.of(context).sourceCode),
|
|
||||||
onPressed: () => launch(AppConfig.sourceCodeUrl),
|
onPressed: () => launch(AppConfig.sourceCodeUrl),
|
||||||
|
child: Text(L10n.of(context).sourceCode),
|
||||||
),
|
),
|
||||||
RaisedButton(
|
OutlinedButton(
|
||||||
child: Text(AppConfig.emojiFontName),
|
|
||||||
onPressed: () => launch(AppConfig.emojiFontUrl),
|
onPressed: () => launch(AppConfig.emojiFontUrl),
|
||||||
|
child: Text(AppConfig.emojiFontName),
|
||||||
),
|
),
|
||||||
SentrySwitchListTile(label: L10n.of(context).sendBugReports),
|
SentrySwitchListTile(label: L10n.of(context).sendBugReports),
|
||||||
],
|
],
|
||||||
|
@ -99,7 +99,7 @@ class UrlLauncher {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
await AdaptivePageLayout.of(context)
|
await AdaptivePageLayout.of(context)
|
||||||
.pushNamedAndRemoveUntilIsFirst('/discover/${roomIdOrAlias}');
|
.pushNamedAndRemoveUntilIsFirst('/discover/$roomIdOrAlias');
|
||||||
}
|
}
|
||||||
} else if (identityParts.primaryIdentifier.sigil == '@') {
|
} else if (identityParts.primaryIdentifier.sigil == '@') {
|
||||||
final user = User(
|
final user = User(
|
||||||
@ -109,7 +109,7 @@ class UrlLauncher {
|
|||||||
var roomId = matrix.client.getDirectChatFromUserId(user.id);
|
var roomId = matrix.client.getDirectChatFromUserId(user.id);
|
||||||
if (roomId != null) {
|
if (roomId != null) {
|
||||||
await AdaptivePageLayout.of(context)
|
await AdaptivePageLayout.of(context)
|
||||||
.pushNamedAndRemoveUntilIsFirst('/rooms/${roomId}');
|
.pushNamedAndRemoveUntilIsFirst('/rooms/$roomId');
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ class UrlLauncher {
|
|||||||
|
|
||||||
if (roomId != null) {
|
if (roomId != null) {
|
||||||
await AdaptivePageLayout.of(context)
|
await AdaptivePageLayout.of(context)
|
||||||
.pushNamedAndRemoveUntilIsFirst('/rooms/${roomId}');
|
.pushNamedAndRemoveUntilIsFirst('/rooms/$roomId');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -636,24 +636,24 @@ class _ChatState extends State<Chat> {
|
|||||||
},
|
},
|
||||||
itemBuilder: (_) => [
|
itemBuilder: (_) => [
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
child: Text(L10n.of(context).copy),
|
|
||||||
value: 'copy',
|
value: 'copy',
|
||||||
|
child: Text(L10n.of(context).copy),
|
||||||
),
|
),
|
||||||
if (canRedactSelectedEvents)
|
if (canRedactSelectedEvents)
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
value: 'redact',
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).redactMessage,
|
L10n.of(context).redactMessage,
|
||||||
style: TextStyle(color: Colors.orange),
|
style: TextStyle(color: Colors.orange),
|
||||||
),
|
),
|
||||||
value: 'redact',
|
|
||||||
),
|
),
|
||||||
if (selectedEvents.length == 1)
|
if (selectedEvents.length == 1)
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
|
value: 'report',
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).reportMessage,
|
L10n.of(context).reportMessage,
|
||||||
style: TextStyle(color: Colors.red),
|
style: TextStyle(color: Colors.red),
|
||||||
),
|
),
|
||||||
value: 'report',
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -672,12 +672,12 @@ class _ChatState extends State<Chat> {
|
|||||||
? Padding(
|
? Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 56.0),
|
padding: const EdgeInsets.only(bottom: 56.0),
|
||||||
child: FloatingActionButton(
|
child: FloatingActionButton(
|
||||||
child: Icon(Icons.arrow_downward_outlined,
|
|
||||||
color: Theme.of(context).primaryColor),
|
|
||||||
onPressed: () => _scrollController.jumpTo(0),
|
onPressed: () => _scrollController.jumpTo(0),
|
||||||
foregroundColor: Theme.of(context).textTheme.bodyText2.color,
|
foregroundColor: Theme.of(context).textTheme.bodyText2.color,
|
||||||
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
||||||
mini: true,
|
mini: true,
|
||||||
|
child: Icon(Icons.arrow_downward_outlined,
|
||||||
|
color: Theme.of(context).primaryColor),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
@ -756,6 +756,7 @@ class _ChatState extends State<Chat> {
|
|||||||
)
|
)
|
||||||
: _canLoadMore
|
: _canLoadMore
|
||||||
? TextButton(
|
? TextButton(
|
||||||
|
onPressed: requestHistory,
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).loadMore,
|
L10n.of(context).loadMore,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -766,7 +767,6 @@ class _ChatState extends State<Chat> {
|
|||||||
TextDecoration.underline,
|
TextDecoration.underline,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: requestHistory,
|
|
||||||
)
|
)
|
||||||
: Container()
|
: Container()
|
||||||
: i == 0
|
: i == 0
|
||||||
@ -790,6 +790,11 @@ class _ChatState extends State<Chat> {
|
|||||||
client.userID
|
client.userID
|
||||||
? Alignment.topRight
|
? Alignment.topRight
|
||||||
: Alignment.topLeft,
|
: Alignment.topLeft,
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 8,
|
||||||
|
right: 8,
|
||||||
|
bottom: 8,
|
||||||
|
),
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
horizontal: 4),
|
horizontal: 4),
|
||||||
@ -810,11 +815,6 @@ class _ChatState extends State<Chat> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.only(
|
|
||||||
left: 8,
|
|
||||||
right: 8,
|
|
||||||
bottom: 8,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -942,14 +942,14 @@ class _ChatState extends State<Chat> {
|
|||||||
itemBuilder: (c, i) => i == emojis.length
|
itemBuilder: (c, i) => i == emojis.length
|
||||||
? InkWell(
|
? InkWell(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
onTap: () => _pickEmojiAction(
|
||||||
|
context, allReactionEvents),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: 56,
|
width: 56,
|
||||||
height: 56,
|
height: 56,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
child: Icon(Icons.add_outlined),
|
child: Icon(Icons.add_outlined),
|
||||||
),
|
),
|
||||||
onTap: () => _pickEmojiAction(
|
|
||||||
context, allReactionEvents),
|
|
||||||
)
|
)
|
||||||
: InkWell(
|
: InkWell(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
@ -249,8 +249,8 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
backgroundColor: Theme.of(context)
|
backgroundColor: Theme.of(context)
|
||||||
.scaffoldBackgroundColor,
|
.scaffoldBackgroundColor,
|
||||||
foregroundColor: Colors.grey,
|
foregroundColor: Colors.grey,
|
||||||
child: Icon(Icons.edit_outlined),
|
|
||||||
radius: Avatar.defaultSize / 2,
|
radius: Avatar.defaultSize / 2,
|
||||||
|
child: Icon(Icons.edit_outlined),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
title: Text('${L10n.of(context).groupDescription}:',
|
title: Text('${L10n.of(context).groupDescription}:',
|
||||||
@ -342,19 +342,6 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
PopupMenuButton(
|
PopupMenuButton(
|
||||||
child: ListTile(
|
|
||||||
leading: CircleAvatar(
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
|
||||||
foregroundColor: Colors.grey,
|
|
||||||
child: Icon(Icons.public_outlined)),
|
|
||||||
title: Text(
|
|
||||||
L10n.of(context).whoIsAllowedToJoinThisGroup),
|
|
||||||
subtitle: Text(
|
|
||||||
room.joinRules.getLocalizedString(
|
|
||||||
MatrixLocals(L10n.of(context))),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onSelected: (JoinRules joinRule) =>
|
onSelected: (JoinRules joinRule) =>
|
||||||
showFutureLoadingDialog(
|
showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@ -377,22 +364,21 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
MatrixLocals(L10n.of(context)))),
|
MatrixLocals(L10n.of(context)))),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
PopupMenuButton(
|
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
foregroundColor: Colors.grey,
|
foregroundColor: Colors.grey,
|
||||||
child: Icon(Icons.visibility_outlined),
|
child: Icon(Icons.public_outlined)),
|
||||||
),
|
|
||||||
title: Text(
|
title: Text(
|
||||||
L10n.of(context).visibilityOfTheChatHistory),
|
L10n.of(context).whoIsAllowedToJoinThisGroup),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
room.historyVisibility.getLocalizedString(
|
room.joinRules.getLocalizedString(
|
||||||
MatrixLocals(L10n.of(context))),
|
MatrixLocals(L10n.of(context))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
PopupMenuButton(
|
||||||
onSelected: (HistoryVisibility historyVisibility) =>
|
onSelected: (HistoryVisibility historyVisibility) =>
|
||||||
showFutureLoadingDialog(
|
showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@ -430,23 +416,23 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
MatrixLocals(L10n.of(context)))),
|
MatrixLocals(L10n.of(context)))),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
if (room.joinRules == JoinRules.public)
|
|
||||||
PopupMenuButton(
|
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Theme.of(context).scaffoldBackgroundColor,
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
foregroundColor: Colors.grey,
|
foregroundColor: Colors.grey,
|
||||||
child: Icon(Icons.info_outline),
|
child: Icon(Icons.visibility_outlined),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
L10n.of(context).areGuestsAllowedToJoin),
|
L10n.of(context).visibilityOfTheChatHistory),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
room.guestAccess.getLocalizedString(
|
room.historyVisibility.getLocalizedString(
|
||||||
MatrixLocals(L10n.of(context))),
|
MatrixLocals(L10n.of(context))),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
if (room.joinRules == JoinRules.public)
|
||||||
|
PopupMenuButton(
|
||||||
onSelected: (GuestAccess guestAccess) =>
|
onSelected: (GuestAccess guestAccess) =>
|
||||||
showFutureLoadingDialog(
|
showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
@ -471,6 +457,20 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
child: ListTile(
|
||||||
|
leading: CircleAvatar(
|
||||||
|
backgroundColor:
|
||||||
|
Theme.of(context).scaffoldBackgroundColor,
|
||||||
|
foregroundColor: Colors.grey,
|
||||||
|
child: Icon(Icons.info_outline),
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
L10n.of(context).areGuestsAllowedToJoin),
|
||||||
|
subtitle: Text(
|
||||||
|
room.guestAccess.getLocalizedString(
|
||||||
|
MatrixLocals(L10n.of(context))),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(L10n.of(context).editChatPermissions),
|
title: Text(L10n.of(context).editChatPermissions),
|
||||||
@ -502,11 +502,11 @@ class _ChatDetailsState extends State<ChatDetails> {
|
|||||||
? ListTile(
|
? ListTile(
|
||||||
title: Text(L10n.of(context).inviteContact),
|
title: Text(L10n.of(context).inviteContact),
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
child: Icon(Icons.add_outlined),
|
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
Theme.of(context).primaryColor,
|
Theme.of(context).primaryColor,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
radius: Avatar.defaultSize / 2,
|
radius: Avatar.defaultSize / 2,
|
||||||
|
child: Icon(Icons.add_outlined),
|
||||||
),
|
),
|
||||||
onTap: () => AdaptivePageLayout.of(context)
|
onTap: () => AdaptivePageLayout.of(context)
|
||||||
.pushNamed('/rooms/${room.id}/invite'),
|
.pushNamed('/rooms/${room.id}/invite'),
|
||||||
|
@ -115,8 +115,8 @@ class _ChatEncryptionSettingsState extends State<ChatEncryptionSettings> {
|
|||||||
.verified ==
|
.verified ==
|
||||||
UserVerifiedStatus.unknown) {
|
UserVerifiedStatus.unknown) {
|
||||||
items.add(PopupMenuItem(
|
items.add(PopupMenuItem(
|
||||||
child: Text(L10n.of(context).verifyUser),
|
|
||||||
value: 'verify_user',
|
value: 'verify_user',
|
||||||
|
child: Text(L10n.of(context).verifyUser),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
@ -162,22 +162,22 @@ class _ChatEncryptionSettingsState extends State<ChatEncryptionSettings> {
|
|||||||
if (deviceKeys[i].blocked ||
|
if (deviceKeys[i].blocked ||
|
||||||
!deviceKeys[i].verified) {
|
!deviceKeys[i].verified) {
|
||||||
items.add(PopupMenuItem(
|
items.add(PopupMenuItem(
|
||||||
child: Text(L10n.of(context).verifyStart),
|
|
||||||
value: deviceKeys[i].userId == room.client.userID
|
value: deviceKeys[i].userId == room.client.userID
|
||||||
? 'verify'
|
? 'verify'
|
||||||
: 'verify_user',
|
: 'verify_user',
|
||||||
|
child: Text(L10n.of(context).verifyStart),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (deviceKeys[i].blocked) {
|
if (deviceKeys[i].blocked) {
|
||||||
items.add(PopupMenuItem(
|
items.add(PopupMenuItem(
|
||||||
child: Text(L10n.of(context).unblockDevice),
|
|
||||||
value: 'unblock',
|
value: 'unblock',
|
||||||
|
child: Text(L10n.of(context).unblockDevice),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (!deviceKeys[i].blocked) {
|
if (!deviceKeys[i].blocked) {
|
||||||
items.add(PopupMenuItem(
|
items.add(PopupMenuItem(
|
||||||
child: Text(L10n.of(context).blockDevice),
|
|
||||||
value: 'block',
|
value: 'block',
|
||||||
|
child: Text(L10n.of(context).blockDevice),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return items;
|
return items;
|
||||||
|
@ -192,6 +192,8 @@ class _ChatListState extends State<ChatList> {
|
|||||||
? Center(
|
? Center(
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
borderRadius: BorderRadius.circular(32),
|
borderRadius: BorderRadius.circular(32),
|
||||||
|
onTap: () => AdaptivePageLayout.of(context)
|
||||||
|
.pushNamedAndRemoveUntilIsFirst('/settings'),
|
||||||
child: FutureBuilder<Profile>(
|
child: FutureBuilder<Profile>(
|
||||||
future: Matrix.of(context).client.ownProfile,
|
future: Matrix.of(context).client.ownProfile,
|
||||||
builder: (_, snapshot) => Avatar(
|
builder: (_, snapshot) => Avatar(
|
||||||
@ -201,8 +203,6 @@ class _ChatListState extends State<ChatList> {
|
|||||||
size: 32,
|
size: 32,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onTap: () => AdaptivePageLayout.of(context)
|
|
||||||
.pushNamedAndRemoveUntilIsFirst('/settings'),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: IconButton(
|
: IconButton(
|
||||||
@ -378,9 +378,9 @@ class _ChatListState extends State<ChatList> {
|
|||||||
]),
|
]),
|
||||||
floatingActionButton: selectMode == SelectMode.normal
|
floatingActionButton: selectMode == SelectMode.normal
|
||||||
? FloatingActionButton(
|
? FloatingActionButton(
|
||||||
child: Icon(Icons.add_outlined),
|
|
||||||
onPressed: () => AdaptivePageLayout.of(context)
|
onPressed: () => AdaptivePageLayout.of(context)
|
||||||
.pushNamedAndRemoveUntilIsFirst('/newprivatechat'),
|
.pushNamedAndRemoveUntilIsFirst('/newprivatechat'),
|
||||||
|
child: Icon(Icons.add_outlined),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
bottomNavigationBar: selectMode == SelectMode.normal
|
bottomNavigationBar: selectMode == SelectMode.normal
|
||||||
|
@ -119,9 +119,9 @@ class _ContactsState extends State<Contacts> {
|
|||||||
ListTile(
|
ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
radius: Avatar.defaultSize / 2,
|
radius: Avatar.defaultSize / 2,
|
||||||
child: Icon(Icons.person_add_outlined),
|
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
|
child: Icon(Icons.person_add_outlined),
|
||||||
),
|
),
|
||||||
title: Text(L10n.of(context).addNewFriend),
|
title: Text(L10n.of(context).addNewFriend),
|
||||||
onTap: () => AdaptivePageLayout.of(context)
|
onTap: () => AdaptivePageLayout.of(context)
|
||||||
@ -141,15 +141,15 @@ class _ContactsState extends State<Contacts> {
|
|||||||
),
|
),
|
||||||
Center(
|
Center(
|
||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
|
onPressed: () => FluffyShare.share(
|
||||||
|
L10n.of(context).inviteText(client.userID,
|
||||||
|
'https://matrix.to/#/${client.userID}'),
|
||||||
|
context),
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).inviteContact,
|
L10n.of(context).inviteContact,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).accentColor),
|
color: Theme.of(context).accentColor),
|
||||||
),
|
),
|
||||||
onPressed: () => FluffyShare.share(
|
|
||||||
L10n.of(context).inviteText(client.userID,
|
|
||||||
'https://matrix.to/#/${client.userID}'),
|
|
||||||
context),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -180,22 +180,16 @@ class _HomeserverPickerState extends State<HomeserverPicker> {
|
|||||||
tag: 'loginButton',
|
tag: 'loginButton',
|
||||||
child: Container(
|
child: Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 56,
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: RaisedButton(
|
child: ElevatedButton(
|
||||||
elevation: 7,
|
onPressed:
|
||||||
color: Theme.of(context).primaryColor,
|
_isLoading ? null : () => _checkHomeserverAction(context),
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
|
||||||
),
|
|
||||||
child: _isLoading
|
child: _isLoading
|
||||||
? LinearProgressIndicator()
|
? LinearProgressIndicator()
|
||||||
: Text(
|
: Text(
|
||||||
L10n.of(context).connect.toUpperCase(),
|
L10n.of(context).connect.toUpperCase(),
|
||||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||||
),
|
),
|
||||||
onPressed:
|
|
||||||
_isLoading ? null : () => _checkHomeserverAction(context),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -203,6 +197,7 @@ class _HomeserverPickerState extends State<HomeserverPicker> {
|
|||||||
alignment: WrapAlignment.center,
|
alignment: WrapAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
|
onPressed: () => launch(AppConfig.privacyUrl),
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).privacy,
|
L10n.of(context).privacy,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -210,9 +205,9 @@ class _HomeserverPickerState extends State<HomeserverPicker> {
|
|||||||
color: Colors.blueGrey,
|
color: Colors.blueGrey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => launch(AppConfig.privacyUrl),
|
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
|
onPressed: () => PlatformInfos.showDialog(context),
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).about,
|
L10n.of(context).about,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -220,7 +215,6 @@ class _HomeserverPickerState extends State<HomeserverPicker> {
|
|||||||
color: Colors.blueGrey,
|
color: Colors.blueGrey,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => PlatformInfos.showDialog(context),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -50,6 +50,15 @@ class ImageView extends StatelessWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: InteractiveViewer(
|
body: InteractiveViewer(
|
||||||
|
minScale: 1.0,
|
||||||
|
maxScale: 10.0,
|
||||||
|
onInteractionEnd: (ScaleEndDetails endDetails) {
|
||||||
|
if (PlatformInfos.usesTouchscreen == false) {
|
||||||
|
if (endDetails.velocity.pixelsPerSecond.dy > calcVelocity) {
|
||||||
|
Navigator.of(context, rootNavigator: false).pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
child: Center(
|
child: Center(
|
||||||
child: ImageBubble(
|
child: ImageBubble(
|
||||||
event,
|
event,
|
||||||
@ -62,15 +71,6 @@ class ImageView extends StatelessWidget {
|
|||||||
thumbnailOnly: false,
|
thumbnailOnly: false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
minScale: 1.0,
|
|
||||||
maxScale: 10.0,
|
|
||||||
onInteractionEnd: (ScaleEndDetails endDetails) {
|
|
||||||
if (PlatformInfos.usesTouchscreen == false) {
|
|
||||||
if (endDetails.velocity.pixelsPerSecond.dy > calcVelocity) {
|
|
||||||
Navigator.of(context, rootNavigator: false).pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,8 @@ class _LogViewerState extends State<LogViewer> {
|
|||||||
PopupMenuButton<Level>(
|
PopupMenuButton<Level>(
|
||||||
itemBuilder: (context) => Level.values
|
itemBuilder: (context) => Level.values
|
||||||
.map((level) => PopupMenuItem(
|
.map((level) => PopupMenuItem(
|
||||||
child: Text(level.toString()),
|
|
||||||
value: level,
|
value: level,
|
||||||
|
child: Text(level.toString()),
|
||||||
))
|
))
|
||||||
.toList(),
|
.toList(),
|
||||||
onSelected: (Level level) => setState(() => logLevel = level),
|
onSelected: (Level level) => setState(() => logLevel = level),
|
||||||
|
@ -10,8 +10,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
import '../utils/platform_infos.dart';
|
import '../utils/platform_infos.dart';
|
||||||
|
|
||||||
import '../app_config.dart';
|
|
||||||
|
|
||||||
class Login extends StatefulWidget {
|
class Login extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_LoginState createState() => _LoginState();
|
_LoginState createState() => _LoginState();
|
||||||
@ -226,27 +224,22 @@ class _LoginState extends State<Login> {
|
|||||||
SizedBox(height: 12),
|
SizedBox(height: 12),
|
||||||
Hero(
|
Hero(
|
||||||
tag: 'loginButton',
|
tag: 'loginButton',
|
||||||
child: Container(
|
child: Padding(
|
||||||
height: 56,
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: RaisedButton(
|
child: ElevatedButton(
|
||||||
elevation: 7,
|
onPressed: loading ? null : () => login(context),
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
|
||||||
),
|
|
||||||
child: loading
|
child: loading
|
||||||
? LinearProgressIndicator()
|
? LinearProgressIndicator()
|
||||||
: Text(
|
: Text(
|
||||||
L10n.of(context).login.toUpperCase(),
|
L10n.of(context).login.toUpperCase(),
|
||||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||||
),
|
),
|
||||||
onPressed: loading ? null : () => login(context),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Center(
|
Center(
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
|
onPressed: () => _passwordForgotten(context),
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).passwordForgotten,
|
L10n.of(context).passwordForgotten,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -254,7 +247,6 @@ class _LoginState extends State<Login> {
|
|||||||
decoration: TextDecoration.underline,
|
decoration: TextDecoration.underline,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () => _passwordForgotten(context),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -91,12 +91,12 @@ class _NewPrivateChatState extends State<NewPrivateChat> {
|
|||||||
elevation: 0,
|
elevation: 0,
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
|
onPressed: () => AdaptivePageLayout.of(context)
|
||||||
|
.pushNamedAndRemoveUntilIsFirst('/newgroup'),
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).createNewGroup,
|
L10n.of(context).createNewGroup,
|
||||||
style: TextStyle(color: Theme.of(context).accentColor),
|
style: TextStyle(color: Theme.of(context).accentColor),
|
||||||
),
|
),
|
||||||
onPressed: () => AdaptivePageLayout.of(context)
|
|
||||||
.pushNamedAndRemoveUntilIsFirst('/newgroup'),
|
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -174,13 +174,13 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
|||||||
),
|
),
|
||||||
floatingActionButton: showSave
|
floatingActionButton: showSave
|
||||||
? FloatingActionButton(
|
? FloatingActionButton(
|
||||||
child: Icon(Icons.save_outlined, color: Colors.white),
|
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await _save(context);
|
await _save(context);
|
||||||
setState(() {
|
setState(() {
|
||||||
showSave = false;
|
showSave = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
child: Icon(Icons.save_outlined, color: Colors.white),
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
body: StreamBuilder(
|
body: StreamBuilder(
|
||||||
@ -190,6 +190,9 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
if (!readonly)
|
if (!readonly)
|
||||||
Container(
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
vertical: 8.0,
|
||||||
|
),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: Container(
|
leading: Container(
|
||||||
width: 180.0,
|
width: 180.0,
|
||||||
@ -222,11 +225,6 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
|||||||
),
|
),
|
||||||
title: _EmoteImagePicker(newMxcController),
|
title: _EmoteImagePicker(newMxcController),
|
||||||
trailing: InkWell(
|
trailing: InkWell(
|
||||||
child: Icon(
|
|
||||||
Icons.add_outlined,
|
|
||||||
color: Colors.green,
|
|
||||||
size: 32.0,
|
|
||||||
),
|
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
if (newEmoteController.text == null ||
|
if (newEmoteController.text == null ||
|
||||||
newEmoteController.text.isEmpty ||
|
newEmoteController.text.isEmpty ||
|
||||||
@ -270,10 +268,12 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
|||||||
showSave = false;
|
showSave = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
child: Icon(
|
||||||
|
Icons.add_outlined,
|
||||||
|
color: Colors.green,
|
||||||
|
size: 32.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
padding: EdgeInsets.symmetric(
|
|
||||||
vertical: 8.0,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (widget.room != null)
|
if (widget.room != null)
|
||||||
@ -346,7 +346,7 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
|||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
),
|
),
|
||||||
onSubmitted: (s) {
|
onSubmitted: (s) {
|
||||||
final emoteCode = ':${s}:';
|
final emoteCode = ':$s:';
|
||||||
if (emotes.indexWhere((e) =>
|
if (emotes.indexWhere((e) =>
|
||||||
e.emote == emoteCode &&
|
e.emote == emoteCode &&
|
||||||
e.mxc != emote.mxc) !=
|
e.mxc != emote.mxc) !=
|
||||||
@ -382,16 +382,16 @@ class _EmotesSettingsState extends State<EmotesSettings> {
|
|||||||
trailing: readonly
|
trailing: readonly
|
||||||
? null
|
? null
|
||||||
: InkWell(
|
: InkWell(
|
||||||
child: Icon(
|
|
||||||
Icons.delete_forever_outlined,
|
|
||||||
color: Colors.red,
|
|
||||||
size: 32.0,
|
|
||||||
),
|
|
||||||
onTap: () => setState(() {
|
onTap: () => setState(() {
|
||||||
emotes.removeWhere(
|
emotes.removeWhere(
|
||||||
(e) => e.emote == emote.emote);
|
(e) => e.emote == emote.emote);
|
||||||
showSave = true;
|
showSave = true;
|
||||||
}),
|
}),
|
||||||
|
child: Icon(
|
||||||
|
Icons.delete_forever_outlined,
|
||||||
|
color: Colors.red,
|
||||||
|
size: 32.0,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -440,14 +440,7 @@ class _EmoteImagePickerState extends State<_EmoteImagePicker> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (widget.controller.text == null || widget.controller.text.isEmpty) {
|
if (widget.controller.text == null || widget.controller.text.isEmpty) {
|
||||||
return RaisedButton(
|
return ElevatedButton(
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
elevation: 5,
|
|
||||||
textColor: Colors.white,
|
|
||||||
child: Text(L10n.of(context).pickImage),
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(10.0),
|
|
||||||
),
|
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
await FlushbarHelper.createError(
|
await FlushbarHelper.createError(
|
||||||
@ -487,6 +480,7 @@ class _EmoteImagePickerState extends State<_EmoteImagePicker> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
child: Text(L10n.of(context).pickImage),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return _EmoteImage(widget.controller.text);
|
return _EmoteImage(widget.controller.text);
|
||||||
|
@ -9,8 +9,6 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||||
|
|
||||||
import '../app_config.dart';
|
|
||||||
|
|
||||||
class SignUp extends StatefulWidget {
|
class SignUp extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
_SignUpState createState() => _SignUpState();
|
_SignUpState createState() => _SignUpState();
|
||||||
@ -138,27 +136,23 @@ class _SignUpState extends State<SignUp> {
|
|||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
Hero(
|
Hero(
|
||||||
tag: 'loginButton',
|
tag: 'loginButton',
|
||||||
child: Container(
|
child: Padding(
|
||||||
height: 56,
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: RaisedButton(
|
child: ElevatedButton(
|
||||||
elevation: 7,
|
onPressed: loading ? null : () => signUpAction(context),
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
|
||||||
),
|
|
||||||
child: loading
|
child: loading
|
||||||
? LinearProgressIndicator()
|
? LinearProgressIndicator()
|
||||||
: Text(
|
: Text(
|
||||||
L10n.of(context).signUp.toUpperCase(),
|
L10n.of(context).signUp.toUpperCase(),
|
||||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||||
),
|
),
|
||||||
onPressed: loading ? null : () => signUpAction(context),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Center(
|
Center(
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
|
onPressed: () =>
|
||||||
|
AdaptivePageLayout.of(context).pushNamed('/login'),
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context).alreadyHaveAnAccount,
|
L10n.of(context).alreadyHaveAnAccount,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
@ -167,8 +161,6 @@ class _SignUpState extends State<SignUp> {
|
|||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: () =>
|
|
||||||
AdaptivePageLayout.of(context).pushNamed('/login'),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
|
@ -10,8 +10,6 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
|
|||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import '../utils/platform_infos.dart';
|
import '../utils/platform_infos.dart';
|
||||||
|
|
||||||
import '../app_config.dart';
|
|
||||||
|
|
||||||
class SignUpPassword extends StatefulWidget {
|
class SignUpPassword extends StatefulWidget {
|
||||||
final MatrixFile avatar;
|
final MatrixFile avatar;
|
||||||
final String username;
|
final String username;
|
||||||
@ -174,22 +172,16 @@ class _SignUpPasswordState extends State<SignUpPassword> {
|
|||||||
SizedBox(height: 12),
|
SizedBox(height: 12),
|
||||||
Hero(
|
Hero(
|
||||||
tag: 'loginButton',
|
tag: 'loginButton',
|
||||||
child: Container(
|
child: Padding(
|
||||||
height: 56,
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||||
child: RaisedButton(
|
child: ElevatedButton(
|
||||||
elevation: 7,
|
onPressed: loading ? null : () => _signUpAction(context),
|
||||||
color: Theme.of(context).primaryColor,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
|
||||||
),
|
|
||||||
child: loading
|
child: loading
|
||||||
? LinearProgressIndicator()
|
? LinearProgressIndicator()
|
||||||
: Text(
|
: Text(
|
||||||
L10n.of(context).createAccountNow.toUpperCase(),
|
L10n.of(context).createAccountNow.toUpperCase(),
|
||||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||||
),
|
),
|
||||||
onPressed: loading ? null : () => _signUpAction(context),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
86
pubspec.lock
86
pubspec.lock
@ -77,7 +77,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.5.0"
|
||||||
base58check:
|
base58check:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -91,7 +91,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.1.0"
|
||||||
cached_network_image:
|
cached_network_image:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -112,14 +112,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.1.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.2.0"
|
||||||
circular_check_box:
|
circular_check_box:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -140,14 +140,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.1.0"
|
||||||
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.15.0"
|
||||||
convert:
|
convert:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -217,7 +217,7 @@ 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.2.0"
|
||||||
famedlysdk:
|
famedlysdk:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -249,7 +249,7 @@ packages:
|
|||||||
name: file
|
name: file
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.2.1"
|
version: "6.1.0"
|
||||||
file_chooser:
|
file_chooser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -386,19 +386,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
flutter_math:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: flutter_math
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.0+2"
|
|
||||||
flutter_matrix_html:
|
flutter_matrix_html:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_matrix_html
|
path: "."
|
||||||
url: "https://pub.dartlang.org"
|
ref: HEAD
|
||||||
source: hosted
|
resolved-ref: b1505570660d2e4c212a67889fe260eca7fb136e
|
||||||
|
url: "https://github.com/ChristianPauly/flutter_matrix_html.git"
|
||||||
|
source: git
|
||||||
version: "0.2.0"
|
version: "0.2.0"
|
||||||
flutter_olm:
|
flutter_olm:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
@ -469,7 +464,7 @@ packages:
|
|||||||
name: flutter_svg
|
name: flutter_svg
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.19.1"
|
version: "0.19.3"
|
||||||
flutter_test:
|
flutter_test:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -570,7 +565,7 @@ packages:
|
|||||||
name: intl
|
name: intl
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.16.1"
|
version: "0.17.0"
|
||||||
io:
|
io:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -591,7 +586,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.2"
|
version: "0.6.3"
|
||||||
localstorage:
|
localstorage:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -626,7 +621,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.10"
|
||||||
matrix_api_lite:
|
matrix_api_lite:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -654,7 +649,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.3.0"
|
||||||
mime:
|
mime:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -768,7 +763,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.8.0"
|
||||||
path_drawing:
|
path_drawing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -824,7 +819,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.2"
|
version: "1.11.0"
|
||||||
permission_handler:
|
permission_handler:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -852,7 +847,7 @@ packages:
|
|||||||
name: platform
|
name: platform
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.1"
|
version: "3.0.0"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -873,14 +868,14 @@ packages:
|
|||||||
name: pool
|
name: pool
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0-nullsafety.2"
|
version: "1.5.0"
|
||||||
process:
|
process:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: process
|
name: process
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.13"
|
version: "4.1.0"
|
||||||
provider:
|
provider:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1032,21 +1027,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.3"
|
version: "2.1.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.2"
|
version: "0.10.10"
|
||||||
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.8.0"
|
||||||
sqflite:
|
sqflite:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1081,21 +1076,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.10.0"
|
||||||
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.1.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.1.0"
|
||||||
swipe_to_action:
|
swipe_to_action:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1116,28 +1111,28 @@ 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.2.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.16.5"
|
||||||
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.19"
|
||||||
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.15"
|
||||||
timezone:
|
timezone:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1145,20 +1140,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.9"
|
version: "0.5.9"
|
||||||
tuple:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: tuple
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.0.3"
|
|
||||||
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.3.0"
|
||||||
unifiedpush:
|
unifiedpush:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@ -1251,7 +1239,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.1.0"
|
||||||
vm_service:
|
vm_service:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -1316,5 +1304,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.2"
|
version: "0.1.2"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.10.2 <2.11.0"
|
dart: ">=2.12.0-0.0 <3.0.0"
|
||||||
flutter: ">=1.22.2 <2.0.0"
|
flutter: ">=1.24.0-10.1.pre"
|
||||||
|
@ -53,7 +53,9 @@ dependencies:
|
|||||||
mime_type: ^0.3.2
|
mime_type: ^0.3.2
|
||||||
flushbar: ^1.10.4
|
flushbar: ^1.10.4
|
||||||
adaptive_dialog: ^0.9.3
|
adaptive_dialog: ^0.9.3
|
||||||
flutter_matrix_html: ^0.2.0
|
flutter_matrix_html:
|
||||||
|
git:
|
||||||
|
url: https://github.com/ChristianPauly/flutter_matrix_html.git
|
||||||
moor: ^3.4.0
|
moor: ^3.4.0
|
||||||
sqlite3_flutter_libs: ^0.3.0
|
sqlite3_flutter_libs: ^0.3.0
|
||||||
sqlite3: ^0.1.8
|
sqlite3: ^0.1.8
|
||||||
@ -73,7 +75,7 @@ dependencies:
|
|||||||
sentry: ">=3.0.0 <4.0.0"
|
sentry: ">=3.0.0 <4.0.0"
|
||||||
scroll_to_index: ^1.0.6
|
scroll_to_index: ^1.0.6
|
||||||
swipe_to_action: ^0.1.0
|
swipe_to_action: ^0.1.0
|
||||||
flutter_svg: 0.19.1 # Because fluffychat depends on flutter_svg >=0.19.2 which requires Flutter SDK version >=1.24.0-6.0.pre <2.0.0, version solving failed.
|
flutter_svg: ^0.19.3
|
||||||
flutter_cache_manager: ^2.1.1
|
flutter_cache_manager: ^2.1.1
|
||||||
open_noti_settings: ^0.0.4
|
open_noti_settings: ^0.0.4
|
||||||
emoji_picker: ^0.1.0
|
emoji_picker: ^0.1.0
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
flutter channel stable
|
|
||||||
flutter upgrade
|
|
||||||
flutter pub get
|
flutter pub get
|
||||||
flutter build apk --release
|
flutter build apk --release
|
||||||
mkdir -p build/android
|
mkdir -p build/android
|
||||||
|
@ -1,4 +1,2 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
flutter channel stable
|
|
||||||
flutter upgrade
|
|
||||||
flutter build apk --debug -v
|
flutter build apk --debug -v
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#!/bin/sh -ve
|
#!/bin/sh -ve
|
||||||
flutter channel stable
|
|
||||||
flutter upgrade
|
|
||||||
flutter clean
|
flutter clean
|
||||||
flutter pub get
|
flutter pub get
|
||||||
cd ios
|
cd ios
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#!/bin/sh -ve
|
#!/bin/sh -ve
|
||||||
flutter channel master && flutter upgrade
|
|
||||||
flutter config --enable-linux-desktop
|
flutter config --enable-linux-desktop
|
||||||
flutter clean
|
flutter clean
|
||||||
flutter pub get
|
flutter pub get
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#!/bin/sh -ve
|
#!/bin/sh -ve
|
||||||
flutter channel dev
|
|
||||||
flutter upgrade
|
|
||||||
flutter config --enable-macos-desktop
|
flutter config --enable-macos-desktop
|
||||||
flutter clean
|
flutter clean
|
||||||
flutter pub get
|
flutter pub get
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#!/bin/sh -ve
|
#!/bin/sh -ve
|
||||||
#flutter channel beta
|
|
||||||
#flutter upgrade
|
|
||||||
flutter config --enable-web
|
flutter config --enable-web
|
||||||
flutter clean
|
flutter clean
|
||||||
flutter pub get
|
flutter pub get
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
flutter channel stable
|
|
||||||
flutter upgrade
|
|
||||||
flutter pub get
|
flutter pub get
|
||||||
flutter build appbundle --target-platform android-arm,android-arm64,android-x64
|
flutter build appbundle --target-platform android-arm,android-arm64,android-x64
|
||||||
mkdir -p build/android
|
mkdir -p build/android
|
||||||
|
Loading…
Reference in New Issue
Block a user