Skip to content

Commit

Permalink
Bug fixes on CloneService
Browse files Browse the repository at this point in the history
  • Loading branch information
iyxan23 authored Jan 31, 2021
2 parents 166d3ca + 0db1c2e commit 4a2b9e8
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,10 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {

if (savedInstanceState != null) savedInstanceState.putParcelableArrayList("items", items);

findViewById(R.id.progressBar_browse).setVisibility(View.GONE);

runOnUiThread(() -> adapter.updateView(items));
runOnUiThread(() -> {
findViewById(R.id.progressBar_browse).setVisibility(View.GONE);
adapter.updateView(items);
});
}).start();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.CollectionReference;
Expand Down Expand Up @@ -181,6 +182,17 @@ public void commitsOnClick(View v) {

// onClick for the "Clone" button
public void cloneOnClick(View v) {
AlertDialog.Builder exists_dialog_builder = new AlertDialog.Builder(this);
exists_dialog_builder.setCancelable(true);
exists_dialog_builder.setTitle("Duplicate Project");
exists_dialog_builder.setMessage("This project already exists in your device (ID: " + project_key + "), are you sure you want to continue?");
exists_dialog_builder.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss());
exists_dialog_builder.setPositiveButton("Yes", (dialog, which) -> {
dialog.dismiss();
do_clone();
});
AlertDialog exists_dialog = exists_dialog_builder.create();

new Thread(() -> {
boolean already_exists = false;
ArrayList<SketchwareProject> projects = Util.fetch_sketchware_projects();
Expand All @@ -199,17 +211,11 @@ public void cloneOnClick(View v) {
}

if (already_exists) {
AlertDialog.Builder exists_dialog = new AlertDialog.Builder(this);
exists_dialog.setCancelable(true);
exists_dialog.setTitle("Duplicate Project");
exists_dialog.setMessage("This project already exists in your device (ID: " + project_key + "), are you sure you want to continue?");
exists_dialog.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss());
exists_dialog.setPositiveButton("Yes", (dialog, which) -> {
dialog.dismiss();
do_clone();
});

exists_dialog.create().show();
runOnUiThread(exists_dialog::show);
} else {
// Clone right away
// Probably will add a confirmation dialog
do_clone();
}
}).start();
}
Expand Down
139 changes: 65 additions & 74 deletions app/src/main/java/com/iyxan23/sketch/collab/services/CloneService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,26 @@
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.os.Process;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.google.android.gms.tasks.Tasks;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.QueryDocumentSnapshot;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QuerySnapshot;
import com.iyxan23.sketch.collab.R;
import com.iyxan23.sketch.collab.Util;
import com.iyxan23.sketch.collab.models.Commit;
import com.iyxan23.sketch.collab.models.SketchwareProject;
import com.iyxan23.sketch.collab.online.ViewOnlineProjectActivity;

import org.json.JSONException;
import org.json.JSONObject;
Expand All @@ -41,12 +39,11 @@

public class CloneService extends Service {

private static final String TAG = "CloneService";

private final String CLONE_CHANNEL_ID = "CLONE_CHANNEL";
private final int NOTIFICATION_ID = 1;

private Looper serviceLooper;
private ServiceHandler serviceHandler;

String project_key;
String project_name;

Expand All @@ -56,16 +53,46 @@ public IBinder onBind(Intent intent) {
return null;
}

// Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
@Override
public void onCreate() {
super.onCreate();
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
project_key = intent.getStringExtra("project_key");
project_name = intent.getStringExtra("project_name");

Intent notificationIntent = new Intent(this, ViewOnlineProjectActivity.class);
notificationIntent.putExtra("project_key", project_key);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);

final Notification.Builder notification_builder;

// Channel ID is for 26+ / Android 8+ / Android Oreo+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createCloneNotificationChannel();

notification_builder = new Notification.Builder(this, CLONE_CHANNEL_ID);
} else {
notification_builder = new Notification.Builder(this);
}

@Override
public void handleMessage(Message msg) {
// Normally we would do some work here, like download a file.
// For our sample, we just sleep for 5 seconds.
Notification notification = notification_builder
.setContentTitle("Cloning Project")
.setContentText("Cloning " + project_name + " (" + project_key + ")")
.setProgress(100, 1, true)
.setSmallIcon(R.drawable.ic_file_download)
.setContentIntent(pendingIntent)
.build();

startForeground(NOTIFICATION_ID, notification);

// Start the cloning on a different thread
Toast.makeText(CloneService.this, "Cloning started.", Toast.LENGTH_SHORT).show();
new Thread(() -> {
try {
FirebaseFirestore firestore = FirebaseFirestore.getInstance();
DocumentReference project = firestore.collection("projects").document(project_key);
Expand All @@ -80,7 +107,7 @@ public void handleMessage(Message msg) {
// Get the snapshot, get the commits, and apply the commits to the snapshot
DocumentSnapshot project_metadata = Tasks.await(project.get());
QuerySnapshot snapshot = Tasks.await(project_snapshot.get());
QuerySnapshot commits = Tasks.await(project_commits .get());
QuerySnapshot commits = Tasks.await(project_commits .orderBy("timestamp", Query.Direction.ASCENDING).get());

for (DocumentSnapshot doc: snapshot.getDocuments()) {
project_data.put(doc.getId(), Util.decrypt(doc.getBlob("data").toBytes()));
Expand All @@ -89,12 +116,16 @@ public void handleMessage(Message msg) {
diff_match_patch dmp = new diff_match_patch();
// Apply the patch
for (DocumentSnapshot commit: commits) {
Commit c = commit.toObject(Commit.class);
HashMap<String, String> patch = (HashMap<String, String>) commit.get("patch");

if (patch == null) continue;

for (String key: keys) {
LinkedList<diff_match_patch.Patch> patches = (LinkedList<diff_match_patch.Patch>) dmp.patch_fromText(c.patch.get(key));
if (!patch.containsKey(key)) continue;

LinkedList<diff_match_patch.Patch> patches = (LinkedList<diff_match_patch.Patch>) dmp.patch_fromText(patch.get(key));
// TODO: CHECK PATCH STATUSES
Object[] result = dmp.patch_apply(patches, c.patch.get(key));
Object[] result = dmp.patch_apply(patches, patch.get(key));

project_data.put(key, (String) result[0]);
}
Expand Down Expand Up @@ -154,49 +185,10 @@ public void handleMessage(Message msg) {
Thread.currentThread().interrupt();
}

Toast.makeText(CloneService.this, "Cloning " + project_name + " finished", Toast.LENGTH_SHORT).show();

// Stop the service using the startId, so that we don't stop
// the service in the middle of handling another job
stopSelf(msg.arg1);
}
}

@Override
public void onCreate() {
// Start up the thread running the service. Note that we create a
// separate thread because the service normally runs in the process's
// main thread, which we don't want to block. We also make it
// background priority so CPU-intensive work doesn't disrupt our UI.
HandlerThread thread = new HandlerThread("aaa",
Process.THREAD_PRIORITY_BACKGROUND);
thread.start();

// Get the HandlerThread's Looper and use it for our Handler
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
}


@Override
public int onStartCommand(Intent intent, int flags, int startId) {
project_key = intent.getStringExtra("project_key");
project_name = intent.getStringExtra("project_name");

Intent notificationIntent = new Intent(this, this.getClass());
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);

Notification notification =
new Notification.Builder(this)
.setContentTitle("Cloning Project")
.setContentText("Cloning " + project_name + " (" + project_key + ")")
.setProgress(100, 1, true)
.setSmallIcon(R.drawable.ic_file_download)
.setContentIntent(pendingIntent)
.build();

startForeground(NOTIFICATION_ID, notification);
stopSelf();
}).start();

return START_NOT_STICKY;
}
Expand All @@ -206,19 +198,18 @@ public void onDestroy() {
super.onDestroy();
}

private void createNotificationChannel() {
@RequiresApi(Build.VERSION_CODES.O)
private void createCloneNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = "Clone Project";
String description = "";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CLONE_CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
CharSequence name = "Clone Project";
String description = "This notification will appear when you clone a project in SketchCollab.";
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CLONE_CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}

0 comments on commit 4a2b9e8

Please sign in to comment.