Skip to content

Commit

Permalink
Merge pull request #1587 from BlueBubblesApp/development
Browse files Browse the repository at this point in the history
v1.6.0
  • Loading branch information
zlshames authored Sep 24, 2021
2 parents d2c425a + e3163d7 commit 17e6bea
Show file tree
Hide file tree
Showing 179 changed files with 9,498 additions and 3,512 deletions.
29 changes: 29 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

linter:
# The lint rules applied to this project can be customized in the
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
# included above or to enable additional rules. A list of all available lints
# and their documentation is published at
# https://dart-lang.github.io/linter/lints/index.html.
#
# Instead of disabling a lint rule for the entire project in the
# section below, it can also be suppressed for a single line of code
# or a specific dart file by using the `// ignore: name_of_lint` and
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
# producing the lint.
rules:
# avoid_print: false # Uncomment to disable the `avoid_print` rule
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options
1 change: 1 addition & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ dependencies {
// implementation 'io.sentry:sentry-android:2.2.2'

implementation 'com.google.mlkit:smart-reply:16.2.0'
implementation 'com.google.mlkit:entity-extraction:16.0.0-beta2'

// for workmanager
implementation "androidx.work:work-runtime:2.5.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ protected void onNewIntent(Intent intent) {
} else {
handleShareFile(intent);
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action)) {
handleSendMultipleImages(intent);
} else {
if (type.equals("NotificationOpen") || type.equals("DirectShare")) {
Expand Down Expand Up @@ -132,6 +132,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
} else if (requestCode == NOTIFICATION_SETTINGS) {
result.success(null);
}
super.onActivityResult(requestCode, resultCode, data);
}

List<String> readPathsFromIntent(Intent intent) {
Expand Down Expand Up @@ -177,7 +178,6 @@ List<String> readPathsFromIntent(Intent intent) {
return images;
}


void handleSendText(Intent intent) {
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
Expand All @@ -188,6 +188,8 @@ void handleSendText(Intent intent) {
id = intent.getStringExtra(Intent.EXTRA_SHORTCUT_ID);
input.put("id", id);
new MethodChannel(engine.getDartExecutor().getBinaryMessenger(), CHANNEL).invokeMethod("shareText", input);
} else {
handleShareFile(intent);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@

import java.sql.Timestamp;
import java.util.Map;
import java.util.Arrays;
import java.util.ArrayList;

import com.bluebubbles.messaging.method_call_handler.handlers.NewMessageNotification;

public class HelperUtils {
public static String TAG = "HelperUtils";
Expand Down Expand Up @@ -73,19 +77,52 @@ public static Bitmap getCircleBitmap(Bitmap bitmap) {
return output;
}

public static void tryCancelNotificationSummary(Context context) {
Log.d(HelperUtils.TAG, "Attempting to cancel notification summary...");
public static void tryCancelNotifications(Context context, Integer existingId, String existingGuid) {
Log.d(HelperUtils.TAG, "Attempting to cancel notifications...");
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
StatusBarNotification[] notifications = manager.getActiveNotifications();
ArrayList<StatusBarNotification> notifications = new ArrayList<StatusBarNotification>(Arrays.asList(manager.getActiveNotifications()));

// We need to keep track of the count manually so that we can accurately clear the summary
Log.d(HelperUtils.TAG, "Notification Count: " + notifications.size());

// Only try to clear a notification if one is provided
for (int i = 0; i < notifications.size(); i++) {
StatusBarNotification sbNotification = notifications.get(i);
Integer nId = sbNotification.getId();
Boolean cancelled = false;

// If we are passed an existing Id,
// clear the notification with that ID
if (existingId != null && nId.equals(existingId)) {
Log.d(HelperUtils.TAG, "Cancelling notification by ID: " + nId.toString());
manager.cancel(NewMessageNotification.notificationTag, nId);
notifications.remove(i);
cancelled = true;
}

// If we were passed an existing chat guid,
// clear the notification if it's from the same chat
if (!cancelled && existingGuid != null) {
String chatGuid = sbNotification.getNotification().extras.getString("chatGuid");
if (chatGuid != null && chatGuid.equals(existingGuid)) {
Log.d(HelperUtils.TAG, "Cancelling notification by Chat GUID: " + chatGuid);
manager.cancel(sbNotification.getTag(), nId);
notifications.remove(i);
}
}
}

// If there are no more notifications (only the group is left). Clear the group
Log.d(HelperUtils.TAG, "Notification Count: " + notifications.length);
if (notifications.length <= 0 || (notifications.length == 1 && notifications[0].getId() == -1)) {
Log.d(HelperUtils.TAG, "Cancelling the notification summary...");
Log.d(HelperUtils.TAG, "Final notification Count: " + notifications.size());

// Using cancel all because it seems cancelling it by ID sometimes doesn't work
notificationManager.cancelAll();
// If there is one notification and that one notification's ID is -1, cancel it
if (notifications.size() == 1 && notifications.get(0).getId() == -1) {
Log.d(HelperUtils.TAG, "Cancelling summary notification");
manager.cancel(-1);
} else if (notifications.size() == 1 && existingId != null && existingId.equals(notifications.get(0).getId())) {
int failedId = notifications.get(0).getId();
Log.d(HelperUtils.TAG, "Failed to cancel notification ID: " + failedId + ". Re-cancelling...");
manager.cancel(NewMessageNotification.notificationTag, failedId);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
package com.bluebubbles.messaging.method_call_handler.handlers;

import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
import android.service.notification.StatusBarNotification;
import android.util.Log;

import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationManagerCompat;

import com.bluebubbles.messaging.MainActivity;
import com.bluebubbles.messaging.method_call_handler.handlers.NewMessageNotification;
import com.bluebubbles.messaging.helpers.HelperUtils;

import java.util.Objects;
Expand Down Expand Up @@ -38,18 +34,7 @@ public ClearChatNotifs(Context context, MethodCall call, MethodChannel.Result r
public void Handle() {
String chatGuid = (String) call.argument("chatGuid");
Log.d(TAG, "Clearing notifications for chat: " + chatGuid);

NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
for (StatusBarNotification statusBarNotification : manager.getActiveNotifications()) {
// Only clear the notification if the Chat GUIDs match
if (statusBarNotification.getNotification().extras.getString("chatGuid") != null && statusBarNotification.getNotification().extras.getString("chatGuid").contains(Objects.requireNonNull(chatGuid))) {
Log.d(TAG, "Cancelling notification with ID: " + statusBarNotification.getId());
notificationManager.cancel(statusBarNotification.getTag(), statusBarNotification.getId());
}
}

HelperUtils.tryCancelNotifications(context, null, chatGuid);
result.success("");
HelperUtils.tryCancelNotificationSummary(context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ public void Handle() {
Boolean messageIsFromMe = (Boolean) call.argument("messageIsFromMe");

// Notification stuff
Integer notificationVisibility = (Integer) call.argument("visibility");
Integer notificationId = (Integer) call.argument("notificationId");
Integer summaryId = (Integer) call.argument("summaryId");
String soundPath = (String) call.argument("sound");
Expand Down Expand Up @@ -159,12 +158,6 @@ public void Handle() {
Bundle extras = new Bundle();
extras.putCharSequence("chatGuid", chatGuid);

// Build the base notification
Integer visibility = Notification.VISIBILITY_PUBLIC;
if (notificationVisibility != null) {
visibility = notificationVisibility;
}

// Create intent for opening the conversation in the app
PendingIntent openIntent = PendingIntent.getActivity(
context,
Expand Down Expand Up @@ -266,8 +259,6 @@ public void Handle() {
.setCategory(NotificationCompat.CATEGORY_MESSAGE)
// Set the priority to high since it's a message they should see
.setPriority(NotificationCompat.PRIORITY_HIGH)
// Set the visibility of the notification
.setVisibility(visibility)
// Sets the intent for when it's clicked
.setContentIntent(openIntent)
// Sets the intent for when it is swiped away
Expand Down Expand Up @@ -345,8 +336,6 @@ public void Handle() {
.setAutoCancel(true)
// Set the priority to high since it's a notification they should see
.setPriority(NotificationCompat.PRIORITY_HIGH)
// Set the visibility of the notification
.setVisibility(visibility)
// Sets the intent for when it's clicked
.setContentIntent(openSummaryIntent)
// Set the color. This is the blue primary color
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,19 +75,9 @@ public void onReceive(Context context, Intent intent) {
} else if (intent.getType().equals("markAsRead")) {
existingId = intent.getExtras().getInt("id");
chatGuid = intent.getExtras().getString("chatGuid");
Log.d(TAG, "Marking chat notification as read: " + intent.getExtras().getString("chatGuid"));
Log.d(TAG, "Finding notifications with ID: " + existingId);

// Clear the chat notification by finding the notification by Tag/ID and cancelling it
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
for (StatusBarNotification statusBarNotification : manager.getActiveNotifications()) {
if (NewMessageNotification.notificationTag.equals(statusBarNotification.getTag()) && statusBarNotification.getId() == existingId) {
notificationManager.cancel(NewMessageNotification.notificationTag, existingId);
}
}
Log.d(TAG, "Marking chat notification as read: " + chatGuid);

HelperUtils.tryCancelNotificationSummary(context);
HelperUtils.tryCancelNotifications(context, existingId, null);

// Build params to send to Dart for it to handle whatever it needs
Map<String, Object> params = new HashMap<>();
Expand All @@ -111,17 +101,7 @@ public void onReceive(Context context, Intent intent) {
}
} else if (intent.getType().equals("swipeAway")) {
existingId = intent.getExtras().getInt("id");

// Clear the chat notification by finding the notification by Tag/ID and cancelling it
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
NotificationManager manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
for (StatusBarNotification statusBarNotification : manager.getActiveNotifications()) {
if (NewMessageNotification.notificationTag.equals(statusBarNotification.getTag()) && statusBarNotification.getId() == existingId) {
notificationManager.cancel(NewMessageNotification.notificationTag, existingId);
}
}

HelperUtils.tryCancelNotificationSummary(context);
HelperUtils.tryCancelNotifications(context, existingId, null);
}
}
}
34 changes: 34 additions & 0 deletions assets/changelog/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@

Below are the last few BlueBubbles App release changelogs

## v1.6.0

**NOTE**: Please update your BlueBubbles Server to v0.2.0 for extended capabilities! If you want to try out BlueBubbles Web/Desktop, v0.2.0 is _required_!

## Changes

### The Big Stuff

* Introducing BlueBubbles for Web (BlueBubbles Server v0.2.0 required)!
- https://bluebubbles.app/web
- https://bluebubbles.app/web/beta (if you'd like to try out beta features)
- BlueBubbles Desktop (new) is still in beta. If you'd like to try it out, join our Discord server!
* Fixes empty notification summary (again)
* Delivery/Read indicators for chats
- Pinned will show an icon, unpinned will show text above the last message date
* Fixes issues with the incorrect last message displaying in the chat list

### The Nitty Gritty

#### New Features
* Adds address, phone number, and email detection within a message
* You can now generate a QR Code on your Android Device to screenshot & save
- The QRCode will only be valid until your server URL changes (never if Dynamic DNS)
* Additional information is now shown in the Connection & Server Management settings page
* Ability to check for Server updates directly from your Android/Web client
* Icons in the iOS theme are now more iOS-y
* Ability to export contacts to your BlueBubbles server so that other clients (Web & Desktop) can use them

#### Bug Fixes
* Fixes layout issues with Smart Replies
* Fixes duplicate message issue when sending a message with a link (separated by a new line)
* Fixes issues sharing .txt files to BlueBubbles
* Tons of other small fixes and cross-platform enhancements

## v1.5.0

## Changes
Expand Down
21 changes: 16 additions & 5 deletions lib/action_handler.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'dart:async';
import 'dart:io';
import 'package:bluebubbles/repository/models/platform_file.dart';
import 'package:flutter/foundation.dart';
import 'package:universal_io/io.dart';

import 'package:bluebubbles/blocs/chat_bloc.dart';
import 'package:bluebubbles/blocs/message_bloc.dart';
Expand Down Expand Up @@ -50,7 +52,7 @@ class ActionHandler {
// Check for URLs
RegExpMatch? linkMatch;
String? linkMsg;
List<RegExpMatch> matches = parseLinks(text);
List<RegExpMatch> matches = parseLinks(text.replaceAll("\n", " "));

// Get the first match (if it exists)
if (matches.length > 0) {
Expand Down Expand Up @@ -175,7 +177,10 @@ class ActionHandler {
});
};

bool isConnected = await InternetConnectionChecker().hasConnection;
bool isConnected = kIsWeb;
if (!isConnected) {
isConnected = await InternetConnectionChecker().hasConnection;
}
if (!isConnected) {
InternetConnectionChecker().checkInterval = Duration(seconds: 1);
StreamSubscription? sub;
Expand Down Expand Up @@ -286,7 +291,12 @@ class ActionHandler {
new QueueItem(
event: "send-attachment",
item: new AttachmentSender(
file,
PlatformFile(
path: file.path,
name: file.path.split("/").last,
size: file.lengthSync(),
bytes: file.readAsBytesSync(),
),
chat,
i == message.attachments!.length - 1 ? message.text ?? "" : "",
),
Expand Down Expand Up @@ -349,7 +359,8 @@ class ActionHandler {
/// resyncChat(chatObj)
/// ```
static Future<void> resyncChat(Chat chat, MessageBloc messageBloc) async {
final Database db = await DBProvider.db.database;
final Database? db = await DBProvider.db.database;
if (db == null) return;
await chat.save();

// Fetch messages associated with the chat
Expand Down
Loading

0 comments on commit 17e6bea

Please sign in to comment.