Performance Debugging
continuous-integration/drone/pr Build is passing
Details
continuous-integration/drone/pr Build is passing
Details
This commit is contained in:
parent
7fba47a1e0
commit
05779c49e2
|
@ -1,4 +1,5 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'package:cwtch/notification_manager.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'package:cwtch/torstatus.dart';
|
import 'package:cwtch/torstatus.dart';
|
||||||
|
@ -14,12 +15,14 @@ class CwtchNotifier {
|
||||||
late Settings settings;
|
late Settings settings;
|
||||||
late ErrorHandler error;
|
late ErrorHandler error;
|
||||||
late TorStatus torStatus;
|
late TorStatus torStatus;
|
||||||
|
late NotificationsManager notificationManager;
|
||||||
|
|
||||||
CwtchNotifier(ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN, TorStatus torStatusCN) {
|
CwtchNotifier(ProfileListState pcn, Settings settingsCN, ErrorHandler errorCN, TorStatus torStatusCN, NotificationsManager notificationManagerP) {
|
||||||
profileCN = pcn;
|
profileCN = pcn;
|
||||||
settings = settingsCN;
|
settings = settingsCN;
|
||||||
error = errorCN;
|
error = errorCN;
|
||||||
torStatus = torStatusCN;
|
torStatus = torStatusCN;
|
||||||
|
notificationManager = notificationManagerP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleMessage(String type, dynamic data) {
|
void handleMessage(String type, dynamic data) {
|
||||||
|
@ -60,6 +63,7 @@ class CwtchNotifier {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "NewMessageFromPeer":
|
case "NewMessageFromPeer":
|
||||||
|
notificationManager.notify("New Message From Peer!");
|
||||||
profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]).unreadMessages++;
|
profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]).unreadMessages++;
|
||||||
profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]).totalMessages++;
|
profileCN.getProfile(data["ProfileOnion"]).contactList.getContact(data["RemotePeer"]).totalMessages++;
|
||||||
profileCN.getProfile(data["ProfileOnion"]).contactList.updateLastMessageTime(data["RemotePeer"], DateTime.now());
|
profileCN.getProfile(data["ProfileOnion"]).contactList.updateLastMessageTime(data["RemotePeer"], DateTime.now());
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cwtch/notification_manager.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:cwtch/cwtch/ffi.dart';
|
import 'package:cwtch/cwtch/ffi.dart';
|
||||||
import 'package:cwtch/cwtch/gomobile.dart';
|
import 'package:cwtch/cwtch/gomobile.dart';
|
||||||
|
@ -50,11 +51,15 @@ class FlwtchState extends State<Flwtch> {
|
||||||
cwtchInit = false;
|
cwtchInit = false;
|
||||||
|
|
||||||
profs = ProfileListState();
|
profs = ProfileListState();
|
||||||
var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus);
|
|
||||||
|
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
|
var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, NullNotificationsManager());
|
||||||
cwtch = CwtchGomobile(cwtchNotifier);
|
cwtch = CwtchGomobile(cwtchNotifier);
|
||||||
|
} else if (Platform.isLinux) {
|
||||||
|
var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, LinuxNotificationsManager());
|
||||||
|
cwtch = CwtchFfi(cwtchNotifier);
|
||||||
} else {
|
} else {
|
||||||
|
var cwtchNotifier = new CwtchNotifier(profs, globalSettings, globalErrorHandler, globalTorStatus, NullNotificationsManager());
|
||||||
cwtch = CwtchFfi(cwtchNotifier);
|
cwtch = CwtchFfi(cwtchNotifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +83,13 @@ class FlwtchState extends State<Flwtch> {
|
||||||
//appStatus = AppModel(cwtch: cwtch);
|
//appStatus = AppModel(cwtch: cwtch);
|
||||||
|
|
||||||
return MultiProvider(
|
return MultiProvider(
|
||||||
providers: [getFlwtchStateProvider(), getProfileListProvider(), getSettingsProvider(), getErrorHandlerProvider(), getTorStatusProvider()],
|
providers: [
|
||||||
|
getFlwtchStateProvider(),
|
||||||
|
getProfileListProvider(),
|
||||||
|
getSettingsProvider(),
|
||||||
|
getErrorHandlerProvider(),
|
||||||
|
getTorStatusProvider(),
|
||||||
|
],
|
||||||
builder: (context, widget) {
|
builder: (context, widget) {
|
||||||
Provider.of<Settings>(context).initPackageInfo();
|
Provider.of<Settings>(context).initPackageInfo();
|
||||||
return Consumer<Settings>(
|
return Consumer<Settings>(
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import 'package:desktop_notifications/desktop_notifications.dart';
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
|
// NotificationsManager provides a wrapper around platform specific notifications logic.
|
||||||
|
abstract class NotificationsManager {
|
||||||
|
Future<void> notify(String message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NullNotificationsManager ignores all notification requests
|
||||||
|
class NullNotificationsManager implements NotificationsManager {
|
||||||
|
@override
|
||||||
|
Future<void> notify(String message) async {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LinuxNotificationsManager uses the desktop_notifications package to implement
|
||||||
|
// the standard dbus-powered linux desktop notifications.
|
||||||
|
class LinuxNotificationsManager implements NotificationsManager {
|
||||||
|
int previous_id = 0;
|
||||||
|
LinuxNotificationsManager() {}
|
||||||
|
Future<void> notify(String message) async {
|
||||||
|
var client = NotificationsClient();
|
||||||
|
var icon_path = Uri.file(path.join(path.current, "cwtch.png"));
|
||||||
|
client.notify('New Message from Peer!', appName: "cwtch", appIcon: icon_path.toString(), replacesId: this.previous_id).then((Notification value) => previous_id = value.id);
|
||||||
|
client.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,48 +31,50 @@ class _ContactsViewState extends State<ContactsView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
endDrawerEnableOpenDragGesture: false,
|
||||||
title: Row(children: [
|
drawerEnableOpenDragGesture: false,
|
||||||
ProfileImage(
|
appBar: AppBar(
|
||||||
imagePath: Provider.of<ProfileInfoState>(context).imagePath,
|
title: RepaintBoundary(
|
||||||
diameter: 42,
|
child: Row(children: [
|
||||||
border: Provider.of<Settings>(context).theme.portraitOnlineBorderColor(),
|
ProfileImage(
|
||||||
badgeTextColor: Colors.red,
|
imagePath: Provider.of<ProfileInfoState>(context).imagePath,
|
||||||
badgeColor: Colors.red,
|
diameter: 42,
|
||||||
),
|
border: Provider.of<Settings>(context).theme.portraitOnlineBorderColor(),
|
||||||
SizedBox(
|
badgeTextColor: Colors.red,
|
||||||
width: 10,
|
badgeColor: Colors.red,
|
||||||
),
|
),
|
||||||
Expanded(
|
SizedBox(
|
||||||
child: Text(
|
width: 10,
|
||||||
"%1 » %2".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname).replaceAll("%2", "Contacts"),
|
),
|
||||||
overflow: TextOverflow.ellipsis,
|
Expanded(
|
||||||
)), //todo
|
child: Text(
|
||||||
]),
|
"%1 » %2".replaceAll("%1", Provider.of<ProfileInfoState>(context).nickname).replaceAll("%2", "Contacts"),
|
||||||
actions: [
|
overflow: TextOverflow.ellipsis,
|
||||||
IconButton(icon: TorIcon(), onPressed: _pushTorStatus),
|
)), //todo
|
||||||
IconButton(
|
])),
|
||||||
icon: Icon(Icons.copy),
|
actions: [
|
||||||
onPressed: _copyOnion,
|
IconButton(icon: TorIcon(), onPressed: _pushTorStatus),
|
||||||
),
|
IconButton(
|
||||||
IconButton(
|
icon: Icon(Icons.copy),
|
||||||
// need both conditions for displaying initial empty textfield and also allowing filters to be cleared if this widget gets lost/reset
|
onPressed: _copyOnion,
|
||||||
icon: Icon(showSearchBar || Provider.of<ContactListState>(context).isFiltered ? Icons.search_off : Icons.search),
|
),
|
||||||
onPressed: () {
|
IconButton(
|
||||||
Provider.of<ContactListState>(context, listen: false).filter = "";
|
// need both conditions for displaying initial empty textfield and also allowing filters to be cleared if this widget gets lost/reset
|
||||||
setState(() {
|
icon: Icon(showSearchBar || Provider.of<ContactListState>(context).isFiltered ? Icons.search_off : Icons.search),
|
||||||
showSearchBar = !showSearchBar;
|
onPressed: () {
|
||||||
});
|
Provider.of<ContactListState>(context, listen: false).filter = "";
|
||||||
})
|
setState(() {
|
||||||
],
|
showSearchBar = !showSearchBar;
|
||||||
),
|
});
|
||||||
floatingActionButton: FloatingActionButton(
|
})
|
||||||
onPressed: _pushAddContact,
|
],
|
||||||
tooltip: AppLocalizations.of(context)!.tooltipAddContact,
|
),
|
||||||
child: const Icon(Icons.person_add_sharp),
|
floatingActionButton: FloatingActionButton(
|
||||||
),
|
onPressed: _pushAddContact,
|
||||||
body: showSearchBar || Provider.of<ContactListState>(context).isFiltered ? _buildFilterable() : _buildContactList(),
|
tooltip: AppLocalizations.of(context)!.tooltipAddContact,
|
||||||
);
|
child: const Icon(Icons.person_add_sharp),
|
||||||
|
),
|
||||||
|
body: showSearchBar || Provider.of<ContactListState>(context).isFiltered ? _buildFilterable() : _buildContactList());
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildFilterable() {
|
Widget _buildFilterable() {
|
||||||
|
@ -89,13 +91,13 @@ class _ContactsViewState extends State<ContactsView> {
|
||||||
|
|
||||||
Widget _buildContactList() {
|
Widget _buildContactList() {
|
||||||
final tiles = Provider.of<ContactListState>(context).contacts.map((ContactInfoState contact) {
|
final tiles = Provider.of<ContactListState>(context).contacts.map((ContactInfoState contact) {
|
||||||
return ChangeNotifierProvider<ContactInfoState>.value(key: ValueKey(contact.profileOnion + "" + contact.onion), value: contact, builder: (_, __) => ContactRow());
|
return ChangeNotifierProvider<ContactInfoState>.value(key: ValueKey(contact.profileOnion + "" + contact.onion), value: contact, builder: (_, __) => RepaintBoundary(child: ContactRow()));
|
||||||
});
|
});
|
||||||
final divided = ListTile.divideTiles(
|
final divided = ListTile.divideTiles(
|
||||||
context: context,
|
context: context,
|
||||||
tiles: tiles,
|
tiles: tiles,
|
||||||
).toList();
|
).toList();
|
||||||
return ListView(children: divided);
|
return RepaintBoundary(child: ListView(children: divided));
|
||||||
}
|
}
|
||||||
|
|
||||||
void _pushAddContact() {
|
void _pushAddContact() {
|
||||||
|
|
|
@ -113,42 +113,43 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
showModalBottomSheet<void>(
|
showModalBottomSheet<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return Container(
|
return RepaintBoundary(
|
||||||
height: 200, // bespoke value courtesy of the [TextField] docs
|
child: Container(
|
||||||
child: Center(
|
height: 200, // bespoke value courtesy of the [TextField] docs
|
||||||
child: Padding(
|
child: Center(
|
||||||
padding: EdgeInsets.all(10.0),
|
child: Padding(
|
||||||
child: Column(
|
padding: EdgeInsets.all(10.0),
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
mainAxisSize: MainAxisSize.min,
|
||||||
Text(AppLocalizations.of(context)!.enterProfilePassword),
|
children: <Widget>[
|
||||||
SizedBox(
|
Text(AppLocalizations.of(context)!.enterProfilePassword),
|
||||||
height: 20,
|
SizedBox(
|
||||||
),
|
height: 20,
|
||||||
CwtchPasswordField(
|
),
|
||||||
controller: ctrlrPassword,
|
CwtchPasswordField(
|
||||||
validator: (value) {},
|
controller: ctrlrPassword,
|
||||||
),
|
validator: (value) {},
|
||||||
SizedBox(
|
),
|
||||||
height: 20,
|
SizedBox(
|
||||||
),
|
height: 20,
|
||||||
Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
|
),
|
||||||
Spacer(),
|
Row(mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [
|
||||||
Expanded(
|
Spacer(),
|
||||||
child: ElevatedButton(
|
Expanded(
|
||||||
child: Text(AppLocalizations.of(context)!.unlock, semanticsLabel: AppLocalizations.of(context)!.unlock),
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
child: Text(AppLocalizations.of(context)!.unlock, semanticsLabel: AppLocalizations.of(context)!.unlock),
|
||||||
Provider.of<FlwtchState>(context, listen: false).cwtch.LoadProfiles(ctrlrPassword.value.text);
|
onPressed: () {
|
||||||
ctrlrPassword.text = "";
|
Provider.of<FlwtchState>(context, listen: false).cwtch.LoadProfiles(ctrlrPassword.value.text);
|
||||||
Navigator.pop(context);
|
ctrlrPassword.text = "";
|
||||||
},
|
Navigator.pop(context);
|
||||||
)),
|
},
|
||||||
Spacer()
|
)),
|
||||||
]),
|
Spacer()
|
||||||
],
|
]),
|
||||||
)),
|
],
|
||||||
));
|
)),
|
||||||
|
)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +158,7 @@ class _ProfileMgrViewState extends State<ProfileMgrView> {
|
||||||
(ProfileInfoState profile) {
|
(ProfileInfoState profile) {
|
||||||
return ChangeNotifierProvider<ProfileInfoState>.value(
|
return ChangeNotifierProvider<ProfileInfoState>.value(
|
||||||
value: profile,
|
value: profile,
|
||||||
builder: (context, child) => ProfileRow(),
|
builder: (context, child) => RepaintBoundary(child: ProfileRow()),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -71,26 +71,27 @@ class MessageBubbleState extends State<MessageBubble> {
|
||||||
|
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
//print(constraints.toString()+", "+constraints.maxWidth.toString());
|
//print(constraints.toString()+", "+constraints.maxWidth.toString());
|
||||||
return Container(
|
return RepaintBoundary(
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(
|
child: Container(
|
||||||
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor(),
|
decoration: BoxDecoration(
|
||||||
border:
|
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor(),
|
||||||
Border.all(color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor(), width: 1),
|
border: Border.all(
|
||||||
borderRadius: BorderRadius.only(
|
color: fromMe ? Provider.of<Settings>(context).theme.messageFromMeBackgroundColor() : Provider.of<Settings>(context).theme.messageFromOtherBackgroundColor(), width: 1),
|
||||||
topLeft: Radius.circular(borderRadiousEh),
|
borderRadius: BorderRadius.only(
|
||||||
topRight: Radius.circular(borderRadiousEh),
|
topLeft: Radius.circular(borderRadiousEh),
|
||||||
bottomLeft: fromMe ? Radius.circular(borderRadiousEh) : Radius.zero,
|
topRight: Radius.circular(borderRadiousEh),
|
||||||
bottomRight: fromMe ? Radius.zero : Radius.circular(borderRadiousEh),
|
bottomLeft: fromMe ? Radius.circular(borderRadiousEh) : Radius.zero,
|
||||||
),
|
bottomRight: fromMe ? Radius.zero : Radius.circular(borderRadiousEh),
|
||||||
),
|
),
|
||||||
child: Padding(
|
),
|
||||||
padding: EdgeInsets.all(9.0),
|
child: Padding(
|
||||||
child: Column(
|
padding: EdgeInsets.all(9.0),
|
||||||
crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
child: Column(
|
||||||
mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start,
|
crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisAlignment: fromMe ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||||
children: fromMe ? [wdgMessage, wdgDecorations] : [wdgSender, wdgMessage, wdgDecorations]))));
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: fromMe ? [wdgMessage, wdgDecorations] : [wdgSender, wdgMessage, wdgDecorations])))));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,41 +15,42 @@ class _MessageListState extends State<MessageList> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext outerContext) {
|
Widget build(BuildContext outerContext) {
|
||||||
return Container(
|
return RepaintBoundary(
|
||||||
child: Scrollbar(
|
child: Container(
|
||||||
isAlwaysShown: true,
|
child: Scrollbar(
|
||||||
controller: ctrlr1,
|
isAlwaysShown: true,
|
||||||
child: Container(
|
|
||||||
// Only show broken heart is the contact is offline...
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
image: Provider.of<ContactInfoState>(outerContext).isOnline()
|
|
||||||
? null
|
|
||||||
: DecorationImage(
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
image: AssetImage("assets/core/negative_heart_512px.png"),
|
|
||||||
colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.mainTextColor(), BlendMode.srcIn))),
|
|
||||||
child: ListView.builder(
|
|
||||||
controller: ctrlr1,
|
controller: ctrlr1,
|
||||||
itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages,
|
child: Container(
|
||||||
reverse: true,
|
// Only show broken heart is the contact is offline...
|
||||||
itemBuilder: (itemBuilderContext, index) {
|
decoration: BoxDecoration(
|
||||||
var trueIndex = Provider.of<ContactInfoState>(outerContext).totalMessages - index - 1;
|
image: Provider.of<ContactInfoState>(outerContext).isOnline()
|
||||||
return ChangeNotifierProvider(
|
? null
|
||||||
key: ValueKey(trueIndex),
|
: DecorationImage(
|
||||||
create: (x) => MessageState(
|
fit: BoxFit.contain,
|
||||||
context: itemBuilderContext,
|
image: AssetImage("assets/core/negative_heart_512px.png"),
|
||||||
profileOnion: Provider.of<ProfileInfoState>(outerContext, listen: false).onion,
|
colorFilter: ColorFilter.mode(Provider.of<Settings>(context).theme.mainTextColor(), BlendMode.srcIn))),
|
||||||
contactHandle: Provider.of<ContactInfoState>(x, listen: false).onion,
|
child: ListView.builder(
|
||||||
messageIndex: trueIndex,
|
controller: ctrlr1,
|
||||||
),
|
itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages,
|
||||||
builder: (bcontext, child) {
|
reverse: true,
|
||||||
String idx = Provider.of<ContactInfoState>(outerContext).isGroup == true && Provider.of<MessageState>(bcontext).signature.isEmpty == false
|
itemBuilder: (itemBuilderContext, index) {
|
||||||
? Provider.of<MessageState>(bcontext).signature
|
var trueIndex = Provider.of<ContactInfoState>(outerContext).totalMessages - index - 1;
|
||||||
: trueIndex.toString();
|
return ChangeNotifierProvider(
|
||||||
return MessageRow(key: Provider.of<ContactInfoState>(bcontext).getMessageKey(idx));
|
key: ValueKey(trueIndex),
|
||||||
});
|
create: (x) => MessageState(
|
||||||
},
|
context: itemBuilderContext,
|
||||||
),
|
profileOnion: Provider.of<ProfileInfoState>(outerContext, listen: false).onion,
|
||||||
)));
|
contactHandle: Provider.of<ContactInfoState>(x, listen: false).onion,
|
||||||
|
messageIndex: trueIndex,
|
||||||
|
),
|
||||||
|
builder: (bcontext, child) {
|
||||||
|
String idx = Provider.of<ContactInfoState>(outerContext).isGroup == true && Provider.of<MessageState>(bcontext).signature.isEmpty == false
|
||||||
|
? Provider.of<MessageState>(bcontext).signature
|
||||||
|
: trueIndex.toString();
|
||||||
|
return RepaintBoundary(child: MessageRow(key: Provider.of<ContactInfoState>(bcontext).getMessageKey(idx)));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,8 @@ class ProfileImage extends StatefulWidget {
|
||||||
class _ProfileImageState extends State<ProfileImage> {
|
class _ProfileImageState extends State<ProfileImage> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Stack(children: [
|
return RepaintBoundary(
|
||||||
|
child: Stack(children: [
|
||||||
ClipOval(
|
ClipOval(
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: Container(
|
child: Container(
|
||||||
|
@ -57,6 +58,6 @@ class _ProfileImageState extends State<ProfileImage> {
|
||||||
child: Text(widget.badgeCount > 99 ? "99+" : widget.badgeCount.toString(), style: TextStyle(color: widget.badgeTextColor, fontSize: 8.0)),
|
child: Text(widget.badgeCount > 99 ? "99+" : widget.badgeCount.toString(), style: TextStyle(color: widget.badgeTextColor, fontSize: 8.0)),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
]);
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ class TorIcon extends StatefulWidget {
|
||||||
class _TorIconState extends State<TorIcon> {
|
class _TorIconState extends State<TorIcon> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Image(
|
return RepaintBoundary(
|
||||||
|
child: Image(
|
||||||
image: AssetImage(Provider.of<TorStatus>(context).progress == 0
|
image: AssetImage(Provider.of<TorStatus>(context).progress == 0
|
||||||
? "assets/core/Tor_OFF.png"
|
? "assets/core/Tor_OFF.png"
|
||||||
: (Provider.of<TorStatus>(context).progress == 100 ? "assets/core/Tor_icon.png" : "assets/core/Tor_Booting_up.png")),
|
: (Provider.of<TorStatus>(context).progress == 100 ? "assets/core/Tor_icon.png" : "assets/core/Tor_Booting_up.png")),
|
||||||
|
@ -25,6 +26,6 @@ class _TorIconState extends State<TorIcon> {
|
||||||
semanticLabel: Provider.of<TorStatus>(context).progress == 100
|
semanticLabel: Provider.of<TorStatus>(context).progress == 100
|
||||||
? AppLocalizations.of(context)!.networkStatusOnline
|
? AppLocalizations.of(context)!.networkStatusOnline
|
||||||
: (Provider.of<TorStatus>(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor),
|
: (Provider.of<TorStatus>(context).progress == 0 ? AppLocalizations.of(context)!.networkStatusDisconnected : AppLocalizations.of(context)!.networkStatusAttemptingTor),
|
||||||
);
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
|
|
||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <window_size/window_size_plugin.h>
|
||||||
|
|
||||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
|
g_autoptr(FlPluginRegistrar) window_size_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "WindowSizePlugin");
|
||||||
|
window_size_plugin_register_with_registrar(window_size_registrar);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
window_size
|
||||||
)
|
)
|
||||||
|
|
||||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||||
|
|
44
pubspec.lock
44
pubspec.lock
|
@ -8,6 +8,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
|
args:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: args
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.0"
|
||||||
async:
|
async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -64,6 +71,20 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "1.0.3"
|
||||||
|
dbus:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dbus
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.0"
|
||||||
|
desktop_notifications:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: desktop_notifications
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.5.0"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -269,6 +290,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.11.0"
|
version: "1.11.0"
|
||||||
|
petitparser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: petitparser
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.0"
|
||||||
platform:
|
platform:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -386,6 +414,15 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.1"
|
version: "2.1.1"
|
||||||
|
window_size:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
path: "plugins/window_size"
|
||||||
|
ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
|
||||||
|
resolved-ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
|
||||||
|
url: "git://github.com/google/flutter-desktop-embedding.git"
|
||||||
|
source: git
|
||||||
|
version: "0.1.0"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -393,6 +430,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.0"
|
version: "0.2.0"
|
||||||
|
xml:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: xml
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "5.1.1"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=2.13.0 <3.0.0"
|
dart: ">=2.13.0 <3.0.0"
|
||||||
flutter: ">=1.20.0"
|
flutter: ">=1.20.0"
|
||||||
|
|
|
@ -34,6 +34,7 @@ dependencies:
|
||||||
cupertino_icons: ^1.0.0
|
cupertino_icons: ^1.0.0
|
||||||
ffi: ^1.0.0
|
ffi: ^1.0.0
|
||||||
path_provider: ^2.0.0
|
path_provider: ^2.0.0
|
||||||
|
desktop_notifications: 0.5.0
|
||||||
|
|
||||||
glob: any
|
glob: any
|
||||||
# todo: flutter_driver causes version conflict. eg https://github.com/flutter/flutter/issues/44829
|
# todo: flutter_driver causes version conflict. eg https://github.com/flutter/flutter/issues/44829
|
||||||
|
@ -44,6 +45,12 @@ dependencies:
|
||||||
flutter_driver:
|
flutter_driver:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
|
window_size:
|
||||||
|
git:
|
||||||
|
url: git://github.com/google/flutter-desktop-embedding.git
|
||||||
|
path: plugins/window_size
|
||||||
|
ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
|
||||||
|
|
||||||
#dev_dependencies:
|
#dev_dependencies:
|
||||||
# flutter_lokalise: any
|
# flutter_lokalise: any
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue