Skip to content

Commit

Permalink
feat: Refine updates changing the fetch interval and behaviour. (#736)
Browse files Browse the repository at this point in the history
Fixes ooni/run#167 ,
ooni/run#168

## Proposed Changes

- Call `Url.checkExistingUrl` when updating descriptor, fixes
ooni/run#168
- Restructure `OverviewActivity` to ensure UI is updated when updates
are accepted.
  -
  • Loading branch information
aanorbel authored May 22, 2024
1 parent 6263520 commit 2879a6e
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private void scheduleWorkers() {
.enqueueUniquePeriodicWork(
AutoUpdateDescriptorsWorker.UPDATED_DESCRIPTORS_WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
new PeriodicWorkRequest.Builder(AutoUpdateDescriptorsWorker.class, 24, TimeUnit.HOURS)
new PeriodicWorkRequest.Builder(AutoUpdateDescriptorsWorker.class, 60, TimeUnit.MINUTES)
.setConstraints(
new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
import android.os.Bundle;
import android.os.Parcelable;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.core.text.TextUtilsCompat;
import androidx.core.view.ViewCompat;
import androidx.databinding.BindingAdapter;
import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.ExistingWorkPolicy;
Expand All @@ -41,15 +43,15 @@
import org.openobservatory.ooniprobe.common.OONITests;
import org.openobservatory.ooniprobe.common.PreferenceManager;
import org.openobservatory.ooniprobe.common.ReadMorePlugin;
import org.openobservatory.ooniprobe.common.TestDescriptorManager;
import org.openobservatory.ooniprobe.common.ThirdPartyServices;
import org.openobservatory.ooniprobe.common.worker.ManualUpdateDescriptorsWorker;
import org.openobservatory.ooniprobe.databinding.ActivityOverviewBinding;
import org.openobservatory.ooniprobe.fragment.ConfirmDialogFragment;
import org.openobservatory.ooniprobe.model.database.InstalledDescriptor;
import org.openobservatory.ooniprobe.model.database.Result;
import org.openobservatory.ooniprobe.model.database.TestDescriptor;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.Objects;

Expand All @@ -68,10 +70,12 @@ public class OverviewActivity extends ReviewUpdatesAbstractActivity implements C
@Inject
OverviewViewModel viewModel;


@Inject
AvailableUpdatesViewModel updatesViewModel;

@Inject
TestDescriptorManager testDescriptorManager;

OverviewTestsExpandableListViewAdapter adapter;

private AbstractDescriptor<BaseNettest> descriptor;
Expand All @@ -87,65 +91,15 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
descriptor = (AbstractDescriptor) getIntent().getSerializableExtra(TEST);
binding = ActivityOverviewBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
viewModel.updateDescriptor(descriptor);
binding.setViewmodel(viewModel);
binding.setLifecycleOwner(this);

setSupportActionBar(binding.toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
setTitle(descriptor.getTitle());
setThemeColor(descriptor.getColor());
binding.icon.setImageResource(descriptor.getDisplayIcon(this));
binding.customUrl.setVisibility(descriptor.getName().equals(OONITests.WEBSITES.getLabel()) ? View.VISIBLE : View.GONE);
Markwon markwon = Markwon.builder(this)
.usePlugin(new ReadMorePlugin(getString(R.string.OONIRun_ReadMore), getString(R.string.OONIRun_ReadLess), 400))
.build();
if (Objects.equals(descriptor.getName(), OONITests.EXPERIMENTAL.name())) {
markwon.setMarkdown(binding.desc, descriptor.getDescription());
if (TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL) {
binding.desc.setTextDirection(View.TEXT_DIRECTION_RTL);
}
} else {
if (descriptor instanceof InstalledDescriptor) {
TestDescriptor testDescriptor = ((InstalledDescriptor) descriptor).getTestDescriptor();
markwon.setMarkdown(
binding.desc,
String.format(
"Created by %s on %s\n\n%s",
testDescriptor.getAuthor(),
new SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH).format(testDescriptor.getDateCreated()),
descriptor.getDescription()
)
);
if (Boolean.TRUE.equals(testDescriptor.isExpired())) {
binding.expiredTag.getRoot().setVisibility(View.VISIBLE);
}

InstalledDescriptor installedDescriptor = ((InstalledDescriptor) descriptor);
if (installedDescriptor.isUpdateAvailable()) {
binding.updatedTag.getRoot().setVisibility(View.VISIBLE);


binding.reviewUpdates.setVisibility(View.VISIBLE);
binding.reviewUpdates.setOnClickListener(view -> getReviewUpdatesLauncher().launch(
ReviewDescriptorUpdatesActivity.newIntent(
OverviewActivity.this,
updatesViewModel.getUpdatedDescriptor(testDescriptor.getRunId())
)
));


}
} else {
markwon.setMarkdown(binding.desc, descriptor.getDescription());
}
}
Result lastResult = Result.getLastResult(descriptor.getName());
if (lastResult == null) {
binding.lastTime.setText(R.string.Dashboard_Overview_LastRun_Never);
} else {
binding.lastTime.setText(DateUtils.getRelativeTimeSpanString(lastResult.start_time.getTime()));
}
onDescriptorLoaded(descriptor);

adapter = new OverviewTestsExpandableListViewAdapter(descriptor.overviewExpandableListViewData(preferenceManager), viewModel);
binding.expandableListView.setAdapter(adapter);
binding.customUrl.setVisibility(descriptor.getName().equals(OONITests.WEBSITES.getLabel()) ? View.VISIBLE : View.GONE);

viewModel.getSelectedAllBtnStatus().observe(this, this::selectAllBtnStatusObserver);
binding.switchTests.addOnCheckedStateChangedListener((checkBox, state) -> {
Expand Down Expand Up @@ -176,20 +130,71 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
binding.switchTests.setCheckedState(MaterialCheckBox.STATE_INDETERMINATE);
}
}
// Expand all groups
for (int i = 0; i < adapter.getGroupCount(); i++) {
binding.expandableListView.expandGroup(i);
}

if (descriptor instanceof InstalledDescriptor) {
if (descriptor instanceof InstalledDescriptor installedDescriptor) {

TestDescriptor testDescriptor = installedDescriptor.getTestDescriptor();

if (Boolean.TRUE.equals(testDescriptor.isExpired())) {
binding.expiredTag.getRoot().setVisibility(View.VISIBLE);
}

if (installedDescriptor.isUpdateAvailable()) {
binding.updatedTag.getRoot().setVisibility(View.VISIBLE);

binding.reviewUpdates.setVisibility(View.VISIBLE);
binding.reviewUpdates.setOnClickListener(view -> getReviewUpdatesLauncher().launch(
ReviewDescriptorUpdatesActivity.newIntent(
OverviewActivity.this,
updatesViewModel.getUpdatedDescriptor(testDescriptor.getRunId())
)
));

}

binding.uninstallLink.setVisibility(View.VISIBLE);
binding.automaticUpdatesContainer.setVisibility(View.VISIBLE);
InstalledDescriptor installedDescriptor = (InstalledDescriptor) descriptor;
binding.automaticUpdatesSwitch.setChecked(installedDescriptor.getTestDescriptor().isAutoUpdate());

} else {
binding.uninstallLink.setVisibility(View.GONE);
/**
* We need to set the height to 0 because the layout is broken when the view is gone
*/
binding.automaticUpdatesContainer.getLayoutParams().height = 0;
}

setUpOnCLickListeners();
registerReviewLauncher(binding.getRoot(), () -> {
binding.reviewUpdates.setVisibility(View.GONE);
try {
onDescriptorLoaded(
new InstalledDescriptor(testDescriptorManager.getById(viewModel.getDescriptor().getValue().getDescriptor().getRunId()), null)
);
} catch (Exception e) {
e.printStackTrace();
}
return null;
});
}

private void onDescriptorLoaded(AbstractDescriptor<BaseNettest> descriptor) {
setTitle(descriptor.getTitle());
setThemeColor(descriptor.getColor());
viewModel.updateDescriptor(descriptor);
binding.executePendingBindings();

adapter = new OverviewTestsExpandableListViewAdapter(descriptor.overviewExpandableListViewData(preferenceManager), viewModel);
binding.expandableListView.setAdapter(adapter);
// Expand all groups
for (int i = 0; i < adapter.getGroupCount(); i++) {
binding.expandableListView.expandGroup(i);
}

if (descriptor instanceof InstalledDescriptor installedDescriptor) {
try {
if (Integer.parseInt(installedDescriptor.getTestDescriptor().getRevision()) > 1) {
getSupportFragmentManager().beginTransaction().add(
getSupportFragmentManager().beginTransaction().replace(
binding.revisionsContainer.getId(),
RevisionsFragment.newInstance(
installedDescriptor.getDescriptor().getRunId(),
Expand All @@ -200,19 +205,8 @@ protected void onCreate(@Nullable Bundle savedInstanceState) {
} catch (Exception e) {
e.printStackTrace();
}
} else {
binding.uninstallLink.setVisibility(View.GONE);
/**
* We need to set the height to 0 because the layout is broken when the view is gone
*/
binding.automaticUpdatesContainer.getLayoutParams().height = 0;
}

setUpOnCLickListeners();
registerReviewLauncher(binding.getRoot(), () -> {
binding.reviewUpdates.setVisibility(View.GONE);
return null;
});
}

private void selectAllBtnStatusObserver(String selectAllBtnStatus) {
Expand Down Expand Up @@ -299,15 +293,26 @@ private void onManualUpdatesFetchComplete(WorkInfo workInfo) {
switch (workInfo.getState()) {
case SUCCEEDED -> {

String descriptor = workInfo.getOutputData().getString(ManualUpdateDescriptorsWorker.KEY_UPDATED_DESCRIPTORS);
if (descriptor != null && !descriptor.isEmpty()) {
binding.reviewUpdates.setVisibility(View.VISIBLE);
binding.reviewUpdates.setOnClickListener(view -> getReviewUpdatesLauncher().launch(
ReviewDescriptorUpdatesActivity.newIntent(
OverviewActivity.this,
descriptor
)
));
String descriptorString = workInfo.getOutputData().getString(ManualUpdateDescriptorsWorker.KEY_UPDATED_DESCRIPTORS);
if (descriptorString != null && !descriptorString.isEmpty()) {
if (descriptor.getDescriptor().isAutoUpdate()) {
testDescriptorManager.updateFromNetwork(descriptorString);
try {
onDescriptorLoaded(
new InstalledDescriptor(testDescriptorManager.getById(viewModel.getDescriptor().getValue().getDescriptor().getRunId()), null)
);
} catch (Exception e) {
e.printStackTrace();
}
} else {
binding.reviewUpdates.setVisibility(View.VISIBLE);
binding.reviewUpdates.setOnClickListener(view -> getReviewUpdatesLauncher().launch(
ReviewDescriptorUpdatesActivity.newIntent(
OverviewActivity.this,
descriptorString
)
));
}
}
binding.swipeRefresh.setRefreshing(false);
}
Expand All @@ -327,10 +332,43 @@ private void onManualUpdatesFetchComplete(WorkInfo workInfo) {
}
}

@Override
protected void onResume() {
super.onResume();
binding.runtime.setText(getString(R.string.twoParam, getString(descriptor.getDataUsage()), getString(R.string.Dashboard_Card_Seconds, String.valueOf(descriptor.getRuntime(this, preferenceManager)))));
@BindingAdapter({"resource"})
public static void setImageViewResource(ImageView imageView, int resource) {
imageView.setImageResource(resource);
}


@BindingAdapter({"dataUsage", "runTime"})
public static void setDataUsage(TextView view, int dataUsage, String runTime) {
Context context = view.getContext();
view.setText(
context.getString(
R.string.twoParam,
context.getString(dataUsage),
context.getString(R.string.Dashboard_Card_Seconds, runTime)
)
);
}

@BindingAdapter(value = {"richText", "testName"})
public static void setRichText(TextView view, String richText, String testName) {
try {
Context context = view.getContext();
Markwon markwon = Markwon.builder(context)
.usePlugin(new ReadMorePlugin(context.getString(R.string.OONIRun_ReadMore), context.getString(R.string.OONIRun_ReadLess), 400))
.build();
if (Objects.equals(testName, OONITests.EXPERIMENTAL.name())) {
markwon.setMarkdown(view, richText);
if (TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL) {
view.setTextDirection(View.TEXT_DIRECTION_RTL);
}
} else {
markwon.setMarkdown(view, richText);
}
} catch (Exception e) {
e.printStackTrace();
ThirdPartyServices.logException(e);
}
}

@Override
Expand Down
Loading

0 comments on commit 2879a6e

Please sign in to comment.