forked from cwtch.im/cwtch-ui
Merge branch 'trunk' into nima/clickable-links
This commit is contained in:
commit
4dea1e1dd4
|
@ -133,6 +133,8 @@ class CwtchNotifier {
|
|||
notificationManager.notify("New Message From Peer!");
|
||||
if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != data["RemotePeer"]) {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.unreadMessages++;
|
||||
} else {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.newMarker++;
|
||||
}
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["RemotePeer"])!.totalMessages++;
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(data["RemotePeer"], DateTime.now());
|
||||
|
@ -181,6 +183,8 @@ class CwtchNotifier {
|
|||
//if not currently open
|
||||
if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != data["GroupID"]) {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.unreadMessages++;
|
||||
} else {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(data["GroupID"])!.newMarker++;
|
||||
}
|
||||
|
||||
var timestampSent = DateTime.tryParse(data['TimestampSent'])!;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "de",
|
||||
"@@last_modified": "2021-11-10T18:47:30+01:00",
|
||||
"@@last_modified": "2021-11-11T01:02:08+01:00",
|
||||
"newMessagesLabel": "New Messages",
|
||||
"localeRU": "Russian",
|
||||
"copyServerKeys": "Copy keys",
|
||||
"verfiyResumeButton": "Verify\/resume",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "en",
|
||||
"@@last_modified": "2021-11-10T18:47:30+01:00",
|
||||
"@@last_modified": "2021-11-11T01:02:08+01:00",
|
||||
"newMessagesLabel": "New Messages",
|
||||
"localeRU": "Russian",
|
||||
"copyServerKeys": "Copy keys",
|
||||
"verfiyResumeButton": "Verify\/resume",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "es",
|
||||
"@@last_modified": "2021-11-10T18:47:30+01:00",
|
||||
"@@last_modified": "2021-11-11T01:02:08+01:00",
|
||||
"newMessagesLabel": "New Messages",
|
||||
"localeRU": "Russian",
|
||||
"copyServerKeys": "Copy keys",
|
||||
"verfiyResumeButton": "Verify\/resume",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "fr",
|
||||
"@@last_modified": "2021-11-10T18:47:30+01:00",
|
||||
"@@last_modified": "2021-11-11T01:02:08+01:00",
|
||||
"newMessagesLabel": "New Messages",
|
||||
"localeRU": "Russian",
|
||||
"copyServerKeys": "Copier les clés",
|
||||
"verfiyResumeButton": "Vérifier\/reprendre",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "it",
|
||||
"@@last_modified": "2021-11-10T18:47:30+01:00",
|
||||
"@@last_modified": "2021-11-11T01:02:08+01:00",
|
||||
"newMessagesLabel": "New Messages",
|
||||
"localeRU": "Russian",
|
||||
"copyServerKeys": "Copy keys",
|
||||
"verfiyResumeButton": "Verify\/resume",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "pl",
|
||||
"@@last_modified": "2021-11-10T18:47:30+01:00",
|
||||
"@@last_modified": "2021-11-11T01:02:08+01:00",
|
||||
"newMessagesLabel": "New Messages",
|
||||
"localeRU": "Russian",
|
||||
"copyServerKeys": "Kopiuj klucze",
|
||||
"verfiyResumeButton": "Zweryfikuj\/wznów",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"@@locale": "pt",
|
||||
"@@last_modified": "2021-11-10T18:47:30+01:00",
|
||||
"@@last_modified": "2021-11-11T01:02:08+01:00",
|
||||
"newMessagesLabel": "New Messages",
|
||||
"localeRU": "Russian",
|
||||
"copyServerKeys": "Copy keys",
|
||||
"verfiyResumeButton": "Verify\/resume",
|
||||
|
|
|
@ -507,6 +507,8 @@ class ContactInfoState extends ChangeNotifier {
|
|||
late int _totalMessages = 0;
|
||||
late DateTime _lastMessageTime;
|
||||
late Map<String, GlobalKey<MessageRowState>> keys;
|
||||
int _newMarker = 0;
|
||||
DateTime _newMarkerClearAt = DateTime.now();
|
||||
|
||||
// todo: a nicer way to model contacts, groups and other "entities"
|
||||
late bool _isGroup;
|
||||
|
@ -587,10 +589,36 @@ class ContactInfoState extends ChangeNotifier {
|
|||
|
||||
int get unreadMessages => this._unreadMessages;
|
||||
set unreadMessages(int newVal) {
|
||||
// don't reset newMarker position when unreadMessages is being cleared
|
||||
if (newVal > 0) {
|
||||
this._newMarker = newVal;
|
||||
} else {
|
||||
this._newMarkerClearAt = DateTime.now().add(const Duration(minutes:2));
|
||||
}
|
||||
this._unreadMessages = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
int get newMarker {
|
||||
if (DateTime.now().isAfter(this._newMarkerClearAt)) {
|
||||
// perform heresy
|
||||
this._newMarker = 0;
|
||||
// no need to notifyListeners() because presumably this getter is
|
||||
// being called from a renderer anyway
|
||||
}
|
||||
return this._newMarker;
|
||||
}
|
||||
// what's a getter that sometimes sets without a setter
|
||||
// that sometimes doesn't set
|
||||
set newMarker(int newVal) {
|
||||
// only unreadMessages++ can set newMarker = 1;
|
||||
// avoids drawing a marker when the convo is already open
|
||||
if (newVal > 1) {
|
||||
this._newMarker = newVal;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
int get totalMessages => this._totalMessages;
|
||||
set totalMessages(int newVal) {
|
||||
this._totalMessages = newVal;
|
||||
|
|
|
@ -4,7 +4,6 @@ import 'package:cwtch/views/torstatusview.dart';
|
|||
import 'package:cwtch/widgets/contactrow.dart';
|
||||
import 'package:cwtch/widgets/profileimage.dart';
|
||||
import 'package:cwtch/widgets/textfield.dart';
|
||||
import 'package:cwtch/widgets/tor_icon.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../main.dart';
|
||||
|
|
|
@ -35,7 +35,7 @@ class _DoubleColumnViewState extends State<DoubleColumnView> {
|
|||
ChangeNotifierProvider.value(value: Provider.of<ProfileInfoState>(context)),
|
||||
ChangeNotifierProvider.value(
|
||||
value: flwtch.selectedConversation != null ? Provider.of<ProfileInfoState>(context).contactList.getContact(flwtch.selectedConversation!)! : ContactInfoState("", "")),
|
||||
], child: Container(child: MessageView())),
|
||||
], child: Container(key: Key(flwtch.selectedConversation??"never_this"), child: MessageView())),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
|
@ -40,15 +40,11 @@ class _MessageViewState extends State<MessageView> {
|
|||
@override
|
||||
void initState() {
|
||||
scrollListener.itemPositions.addListener(() {
|
||||
if (scrollListener.itemPositions.value.length == 0) {
|
||||
return;
|
||||
}
|
||||
var first = scrollListener.itemPositions.value.first.index;
|
||||
var last = scrollListener.itemPositions.value.last.index;
|
||||
// sometimes these go hi->lo and sometimes they go lo->hi because [who tf knows]
|
||||
if ((first == 0 || last == 0) && Provider.of<AppState>(context, listen: false).unreadMessagesBelow == true) {
|
||||
Provider.of<AppState>(context, listen: false).initialScrollIndex = 0;
|
||||
Provider.of<AppState>(context, listen: false).unreadMessagesBelow = false;
|
||||
if (scrollListener.itemPositions.value.length != 0 &&
|
||||
Provider.of<AppState>(context, listen: false).unreadMessagesBelow == true &&
|
||||
scrollListener.itemPositions.value.any((element) => element.index == 0)) {
|
||||
Provider.of<AppState>(context, listen: false).initialScrollIndex = 0;
|
||||
Provider.of<AppState>(context, listen: false).unreadMessagesBelow = false;
|
||||
}
|
||||
});
|
||||
super.initState();
|
||||
|
@ -59,7 +55,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
var appState = Provider.of<AppState>(context, listen: false);
|
||||
|
||||
// using "8" because "# of messages that fit on one screen" isnt trivial to calculate at this point
|
||||
if (appState.initialScrollIndex > 8 && appState.unreadMessagesBelow == false) {
|
||||
if (appState.initialScrollIndex > 4 && appState.unreadMessagesBelow == false) {
|
||||
WidgetsFlutterBinding.ensureInitialized().addPostFrameCallback((timeStamp) {
|
||||
appState.unreadMessagesBelow = true;
|
||||
});
|
||||
|
@ -111,6 +107,8 @@ class _MessageViewState extends State<MessageView> {
|
|||
? FloatingActionButton(
|
||||
child: Icon(Icons.arrow_downward),
|
||||
onPressed: () {
|
||||
Provider.of<AppState>(context, listen: false).initialScrollIndex = 0;
|
||||
Provider.of<AppState>(context, listen: false).unreadMessagesBelow = false;
|
||||
scrollController.scrollTo(index: 0, duration: Duration(milliseconds: 600));
|
||||
})
|
||||
: null,
|
||||
|
@ -216,6 +214,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
focusNode.requestFocus();
|
||||
Future.delayed(const Duration(milliseconds: 80), () {
|
||||
Provider.of<ContactInfoState>(context, listen: false).totalMessages++;
|
||||
Provider.of<ContactInfoState>(context, listen: false).newMarker++;
|
||||
// Resort the contact list...
|
||||
Provider.of<ProfileInfoState>(context, listen: false).contactList.updateLastMessageTime(Provider.of<ContactInfoState>(context, listen: false).onion, DateTime.now());
|
||||
});
|
||||
|
|
|
@ -71,7 +71,7 @@ class _MessageListState extends State<MessageList> {
|
|||
? ScrollablePositionedList.builder(
|
||||
itemPositionsListener: widget.scrollListener,
|
||||
itemScrollController: widget.scrollController,
|
||||
initialScrollIndex: Provider.of<AppState>(outerContext, listen: false).initialScrollIndex,
|
||||
initialScrollIndex: initi > 4 ? initi - 4 : 0,
|
||||
itemCount: Provider.of<ContactInfoState>(outerContext).totalMessages,
|
||||
reverse: true, // NOTE: There seems to be a bug in flutter that corrects the mouse wheel scroll, but not the drag direction...
|
||||
itemBuilder: (itemBuilderContext, index) {
|
||||
|
|
|
@ -159,7 +159,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
];
|
||||
}
|
||||
var size = MediaQuery.of(context).size;
|
||||
return MouseRegion(
|
||||
var mr = MouseRegion(
|
||||
// For desktop...
|
||||
onHover: (event) {
|
||||
setState(() {
|
||||
|
@ -197,6 +197,31 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: widgetRow,
|
||||
)))));
|
||||
var mark = Provider.of<ContactInfoState>(context).newMarker;
|
||||
if (mark > 0 && mark == Provider.of<ContactInfoState>(context).totalMessages - Provider.of<MessageMetadata>(context).messageIndex) {
|
||||
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Align(alignment:Alignment.center ,child:_bubbleNew()), mr]);
|
||||
} else {
|
||||
return mr;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _bubbleNew() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeBackgroundColor(),
|
||||
border: Border.all(
|
||||
color: Provider.of<Settings>(context).theme.messageFromMeBackgroundColor(),
|
||||
width: 1),
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(8),
|
||||
topRight: Radius.circular(8),
|
||||
bottomLeft: Radius.circular(8),
|
||||
bottomRight: Radius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(9.0),
|
||||
child: Text(AppLocalizations.of(context)!.newMessagesLabel)));
|
||||
}
|
||||
|
||||
void _runAnimation(Offset pixelsPerSecond, Size size) {
|
||||
|
|
Loading…
Reference in New Issue