Pinning Conversations
continuous-integration/drone/pr Build is passing Details

This commit is contained in:
Sarah Jamie Lewis 2022-07-22 09:38:51 -07:00
parent 3a752b7397
commit 546ac6c23d
21 changed files with 132 additions and 32 deletions

View File

@ -1 +1 @@
2022-07-06-15-49-v1.8.0-4-g4417347
2022-07-22-12-41-v1.8.0-7-g7b3e842

View File

@ -1 +1 @@
2022-07-06-19-50-v1.8.0-4-g4417347
2022-07-22-16-41-v1.8.0-7-g7b3e842

View File

@ -1,6 +1,9 @@
{
"@@locale": "cy",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "da",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "de",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "el",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "en",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "es",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,13 +1,16 @@
{
"@@locale": "fr",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",
"viewReplies": "View replies to this message",
"restartFileShare": "Start Sharing File",
"stopSharingFile": "Stop Sharing File",
"manageSharedFiles": "Manage Shared Files",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"viewReplies": "Voir les réponses à ce message",
"stopSharingFile": "Arrêter le partage de fichiers",
"restartFileShare": "Démarrer le partage de fichiers",
"replyingTo": "Répondre à %1",
"messageNoReplies": "Il n'y a pas de réponses à ce message.",
"manageSharedFiles": "Gérer les fichiers partagés",
"headingReplies": "Réponses",
"fileDownloadUnavailable": "Ce fichier semble indisponible pour le téléchargement. L'expéditeur a peut-être désactivé les téléchargements pour ce fichier.",
"localeDe": "Allemand \/ Deutsch",
"localeDa": "Danois \/ Dansk",
"localePt": "Portugais \/ Portuguesa",

View File

@ -1,13 +1,16 @@
{
"@@locale": "it",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",
"viewReplies": "View replies to this message",
"restartFileShare": "Start Sharing File",
"stopSharingFile": "Stop Sharing File",
"manageSharedFiles": "Manage Shared Files",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"fileDownloadUnavailable": "Questo file non sembra disponibile per il download. Il mittente potrebbe aver disabilitato i download per questo file.",
"headingReplies": "Risposte",
"manageSharedFiles": "Gestisci file condivisi",
"messageNoReplies": "Non ci sono risposte a questo messaggio.",
"replyingTo": "Risposta a %1",
"restartFileShare": "Avvia la condivisione del file",
"stopSharingFile": "Interrompi la condivisione del file",
"viewReplies": "Visualizza le risposte a questo messaggio",
"localeDe": "Tedesco \/ Deutsch",
"settingImagePreviewsDescription": "Le immagini e le immagini del profilo verranno scaricate e visualizzate in anteprima automaticamente. Ti consigliamo di non abilitare questo esperimento se usi Cwtch con contatti non attendibili.",
"localeNo": "Norvegese \/ Norsk",

View File

@ -1,6 +1,9 @@
{
"@@locale": "lb",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "no",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "pl",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "pt",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "ro",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
{
"@@locale": "ru",
"@@last_modified": "2022-07-07T22:32:20+02:00",
"@@last_modified": "2022-07-21T19:54:08+02:00",
"tooltipUnpinConversation": "Unpin conversation from the top of \"Conversations\"",
"tooltipPinConversation": "Pin conversation to the top of \"Conversations\"",
"replyingTo": "Replying to %1",
"fileDownloadUnavailable": "This file appears unavailable for download. The sender may have disabled downloads for this file.",
"messageNoReplies": "There are no replies to this message.",
"headingReplies": "Replies",

View File

@ -1,6 +1,9 @@
import 'package:cwtch/main.dart';
import 'package:cwtch/models/profile.dart';
import 'package:cwtch/widgets/messagerow.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:provider/provider.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';
import 'message.dart';
@ -51,6 +54,7 @@ class ContactInfoState extends ChangeNotifier {
late bool _isGroup;
String? _server;
late bool _archived;
late bool _pinned;
String? _acnCircuit;
@ -68,7 +72,8 @@ class ContactInfoState extends ChangeNotifier {
lastMessageTime,
server,
archived = false,
notificationPolicy = "ConversationNotificationPolicy.Default"}) {
notificationPolicy = "ConversationNotificationPolicy.Default",
pinned = false}) {
this._nickname = nickname;
this._isGroup = isGroup;
this._accepted = accepted;
@ -84,6 +89,7 @@ class ContactInfoState extends ChangeNotifier {
this._archived = archived;
this._notificationPolicy = notificationPolicyFromString(notificationPolicy);
this.messageCache = new MessageCache(_totalMessages);
this._pinned = pinned;
keys = Map<String, GlobalKey<MessageRowState>>();
}
@ -285,4 +291,27 @@ class ContactInfoState extends ChangeNotifier {
}
return ConversationNotificationPolicy.Never;
}
bool get pinned {
return _pinned;
}
// Pin the conversation to the top of the conversation list
// Requires caller tree to contain a FlwtchState and ProfileInfoState provider.
void pin(context) {
_pinned = true;
var profileHandle = Provider.of<ProfileInfoState>(context, listen: false).onion;
Provider.of<FlwtchState>(context,listen: false).cwtch.SetConversationAttribute(profileHandle, identifier, "profile.pinned", "true");
notifyListeners();
}
// Unpin the conversation from the top of the conversation list
// Requires caller tree to contain a FlwtchState and ProfileInfoState provider.
void unpin(context) {
_pinned = false;
var profileHandle = Provider.of<ProfileInfoState>(context,listen: false).onion;
Provider.of<FlwtchState>(context,listen: false).cwtch.SetConversationAttribute(profileHandle, identifier, "profile.pinned", "false");
notifyListeners();
}
}

View File

@ -51,6 +51,9 @@ class ContactListState extends ChangeNotifier {
// return -1 = a first in list
// return 1 = b first in list
// pinned contacts first
if (a.pinned != true && b.pinned == true) return 1;
if (a.pinned == true && b.pinned != true) return -1;
// blocked contacts last
if (a.isBlocked == true && b.isBlocked != true) return 1;
if (a.isBlocked != true && b.isBlocked == true) return -1;

View File

@ -67,6 +67,7 @@ class ProfileInfoState extends ChangeNotifier {
server: contact["groupServer"],
archived: contact["isArchived"] == true,
lastMessageTime: DateTime.fromMillisecondsSinceEpoch(1000 * int.parse(contact["lastMsgTime"])),
pinned: contact["attributes"]?["local.profile.pinned"] == "true",
notificationPolicy: contact["notificationPolicy"] ?? "ConversationNotificationPolicy.Default");
}));

View File

@ -1,3 +1,4 @@
import 'package:cwtch/config.dart';
import 'package:flutter/cupertino.dart';
import 'contact.dart';
@ -13,7 +14,7 @@ class RemoteServerInfoState extends ChangeNotifier {
DateTime lastPreSyncMessagTime = new DateTime(2020);
RemoteServerInfoState(this.onion, this.identifier, this.description, this._status, {lastPreSyncMessageTime, mostRecentMessageTime}) {
if (_status == "Authenticated") {
if (_status == "Authenticated" || _status == "Synced") {
this.lastPreSyncMessagTime = lastPreSyncMessageTime;
updateSyncProgressFor(mostRecentMessageTime);
}

View File

@ -2,6 +2,7 @@ import 'dart:io';
import 'package:cwtch/models/appstate.dart';
import 'package:cwtch/models/contact.dart';
import 'package:cwtch/models/contactlist.dart';
import 'package:cwtch/models/profile.dart';
import 'package:cwtch/views/contactsview.dart';
import 'package:flutter/material.dart';
@ -18,6 +19,9 @@ class ContactRow extends StatefulWidget {
}
class _ContactRowState extends State<ContactRow> {
bool isHover = false;
@override
Widget build(BuildContext context) {
var contact = Provider.of<ContactInfoState>(context);
@ -123,10 +127,30 @@ class _ContactRowState extends State<ContactRow> {
),
],
))),
Visibility(visible: Platform.isAndroid || (!Platform.isAndroid && isHover) || contact.pinned, child:
IconButton(
tooltip: contact.pinned ? AppLocalizations.of(context)!.tooltipUnpinConversation :AppLocalizations.of(context)!.tooltipPinConversation ,
icon: Icon(contact.pinned ? Icons.push_pin : Icons.push_pin_outlined,
color: Provider.of<Settings>(context).theme.mainTextColor,),
onPressed: () {
if (contact.pinned) {
contact.unpin(context);
} else {
contact.pin(context);
}
Provider.of<ContactListState>(context, listen: false).resort();
},
))
]),
onTap: () {
selectConversation(context, contact.identifier);
},
onHover: (onHover) {
setState(() {
isHover = onHover;
});
},
));
}