Add Tracker Page instead of opening external web page

This commit is contained in:
Schoumi 2020-06-29 17:39:48 +02:00
parent a13342a145
commit 5241f4cb10
11 changed files with 578 additions and 11 deletions

View File

@ -40,12 +40,15 @@ import com.google.android.material.snackbar.Snackbar;
import org.eu.exodus_privacy.exodusprivacy.adapters.ApplicationListAdapter;
import org.eu.exodus_privacy.exodusprivacy.adapters.ApplicationViewModel;
import org.eu.exodus_privacy.exodusprivacy.adapters.TrackerListAdapter;
import org.eu.exodus_privacy.exodusprivacy.databinding.MainBinding;
import org.eu.exodus_privacy.exodusprivacy.fragments.HomeFragment;
import org.eu.exodus_privacy.exodusprivacy.fragments.ReportFragment;
import org.eu.exodus_privacy.exodusprivacy.fragments.TrackerFragment;
import org.eu.exodus_privacy.exodusprivacy.fragments.Updatable;
import org.eu.exodus_privacy.exodusprivacy.listener.NetworkListener;
import org.eu.exodus_privacy.exodusprivacy.manager.DatabaseManager;
import java.util.ArrayList;
import java.util.List;
@ -57,6 +60,7 @@ public class MainActivity extends AppCompatActivity {
private MenuItem settingsMenuItem;
private String packageName;
private MainBinding binding;
private ApplicationListAdapter.OnAppClickListener onAppClickListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -100,12 +104,24 @@ public class MainActivity extends AppCompatActivity {
}
};
ApplicationListAdapter.OnAppClickListener onAppClickListener = vm -> {
TrackerListAdapter.OnTrackerClickListener onTrackerClickListener = id -> {
TrackerFragment tracker = TrackerFragment.newInstance(id);
tracker.setOnAppClickListener(onAppClickListener);
fragments.add(tracker);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_right, R.anim.slide_in_left, R.anim.slide_out_left)
.replace(R.id.fragment_container,tracker)
.addToBackStack(null)
.commit();
};
onAppClickListener = vm -> {
try {
PackageManager pm = getPackageManager();
PackageInfo packageInfo = pm.getPackageInfo(vm.packageName, PackageManager.GET_PERMISSIONS);
ReportFragment report = ReportFragment.newInstance(pm,vm,packageInfo);
ReportFragment report = ReportFragment.newInstance(pm,vm,packageInfo,onTrackerClickListener);
fragments.add(report);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();

View File

@ -12,6 +12,9 @@ import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Utils {
@ -79,4 +82,143 @@ public class Utils {
}
return str.toString();
}
/*
Simple and not complete markdownToHtml converter
*/
public static String markdownToHtml(String markdown) {
StringBuilder builder = new StringBuilder();
String[] lines = markdown.split("\r\n");
ArrayList<String> listStarter = new ArrayList<>();
ArrayList<String> formatStarter = new ArrayList<>();
ArrayList<String> closeTags = new ArrayList<>();
for(String line : lines) {
if (line.matches("^#{1,5} .*")) {
int nb = line.indexOf(" ");
String hx = "<h"+nb+">";
String endhx = "</h"+nb+">";
builder.append(hx);
closeTags.add(endhx);
line = line.substring(line.indexOf(" ")+1);
} else if (line.matches("^ *[+\\-*] .*")) {
String starter="";
if (listStarter.size() > 0 && line.startsWith(listStarter.get(listStarter.size()-1))) {
starter = listStarter.get(listStarter.size()-1);
} else {
Pattern pattern = Pattern.compile("^( *[+\\-*] )");
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
starter = matcher.group(1);
listStarter.add(starter);
builder.append("<ul>\n");
}
}
builder.append("<li> ");
int beginIndex = line.indexOf(starter)+starter.length();
line = line.substring(beginIndex);
closeTags.add("</li>");
} else {
while(!listStarter.isEmpty()) {
listStarter.remove(listStarter.size() - 1);
builder.append("</ul>\n");
}
builder.append("<p>");
closeTags.add("</p>");
}
while(!line.isEmpty()){
Pattern pattern = Pattern.compile("^\\[(.+?)(?=\\]\\()\\]\\((http.+?)(?=\\))\\)");
//Pattern pattern = Pattern.compile("^\\[(.*)\\]\\((http.*)\\)");
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
builder.append("<a href=\"");
builder.append(matcher.group(2));
builder.append("\">");
builder.append(matcher.group(1));
builder.append("</a>");
line = line.substring(line.indexOf(")")+1);
continue;
}
pattern = Pattern.compile("^(http.*)");
matcher = pattern.matcher(line);
if (matcher.find()) {
builder.append("<a href=\"");
builder.append(matcher.group(1));
builder.append("\">");
builder.append(matcher.group(1));
builder.append("</a>");
line = line.substring(matcher.group(1).length());
continue;
}
pattern = Pattern.compile("^[*_]{2}(.+)[*_]{2}");
matcher = pattern.matcher(line);
if (matcher.find()) {
if(line.startsWith("*")) {
line = line.replaceFirst("\\*\\*", "<b>");
formatStarter.add("**");
}
else {
line = line.replaceFirst("__", "<b>");
formatStarter.add("__");
}
continue;
}
pattern = Pattern.compile("^[*_]{1}(.+)");
matcher = pattern.matcher(line);
if (matcher.find()) {
if(line.startsWith("*")) {
line = line.replaceFirst("\\*", "<i>");
formatStarter.add("*");
}
else {
line = line.replaceFirst("_", "<i>");
formatStarter.add("_");
}
continue;
}
if(formatStarter.size() > 0) {
String checkFormat;
if(line.contains(" "))
checkFormat = line.substring(0,line.indexOf(" "));
else
checkFormat = line;
String lastFormat = formatStarter.get(formatStarter.size()-1);
if (checkFormat.contains(lastFormat)) {
if(lastFormat.length()==2) {
if (lastFormat.contains("*"))
line = line.replaceFirst("\\*\\*", "</b>");
else
line = line.replaceFirst("__", "</b>");
} else {
if (lastFormat.contains("*"))
line = line.replaceFirst("\\*", "</i>");
else
line = line.replaceFirst("_", "</i>");
}
formatStarter.remove(formatStarter.size()-1);
continue;
}
}
if(line.contains(" ")) {
builder.append(line.substring(0, line.indexOf(" ") + 1));
line = line.substring(line.indexOf(" ") + 1);
} else {
builder.append(line);
line = "";
}
}
//close all unclosed tags starting at the end
while(!closeTags.isEmpty()) {
builder.append(closeTags.remove(closeTags.size()-1));
}
builder.append("\n");
}
while(!listStarter.isEmpty()) {
listStarter.remove(listStarter.size() - 1);
builder.append("</ul>\n");
}
return builder.toString();
}
}

View File

@ -3,7 +3,6 @@ package org.eu.exodus_privacy.exodusprivacy.adapters;
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
@ -24,11 +23,13 @@ import java.util.Set;
public class TrackerListAdapter extends RecyclerView.Adapter<TrackerListAdapter.TrackerListViewHolder>{
private List<Tracker> trackersList;
private OnTrackerClickListener trackerClickListener;
private int layout;
public TrackerListAdapter(Set<Tracker> trackerList, int resource) {
public TrackerListAdapter(Set<Tracker> trackerList, int resource, OnTrackerClickListener listener) {
setTrackers(trackerList);
layout = resource;
trackerClickListener = listener;
}
@NonNull
@ -78,9 +79,7 @@ public class TrackerListAdapter extends RecyclerView.Adapter<TrackerListAdapter.
if(tracker != null) {
binding.trackerName.setText(tracker.name + "");
binding.getRoot().setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://reports.exodus-privacy.eu.org/trackers/" + tracker.id + "/"));
v.getContext().startActivity(intent);
trackerClickListener.onTrackerClick(tracker.id);
});
}
else
@ -89,5 +88,9 @@ public class TrackerListAdapter extends RecyclerView.Adapter<TrackerListAdapter.
}
}
public interface OnTrackerClickListener{
public void onTrackerClick(long trackerId);
}
}

View File

@ -49,13 +49,15 @@ public class ReportFragment extends Fragment implements Updatable {
private PackageManager packageManager;
private PackageInfo packageInfo = null;
private ReportBinding reportBinding;
private TrackerListAdapter.OnTrackerClickListener trackerClickListener;
private ApplicationViewModel model;
public static ReportFragment newInstance(PackageManager packageManager,ApplicationViewModel model, PackageInfo packageInfo) {
public static ReportFragment newInstance(PackageManager packageManager,ApplicationViewModel model, PackageInfo packageInfo, TrackerListAdapter.OnTrackerClickListener trackerClickListener) {
ReportFragment fragment = new ReportFragment();
fragment.setPackageManager(packageManager);
fragment.setPackageInfo(packageInfo);
fragment.setApplicationViewModel(model);
fragment.setOnTrackerClickListener(trackerClickListener);
return fragment;
}
@ -107,7 +109,7 @@ public class ReportFragment extends Fragment implements Updatable {
//setup trackers lists
reportBinding.trackers.setLayoutManager(new LinearLayoutManager(context));
TrackerListAdapter trackerAdapter = new TrackerListAdapter(reportDisplay.trackers,R.layout.tracker_item);
TrackerListAdapter trackerAdapter = new TrackerListAdapter(reportDisplay.trackers,R.layout.tracker_item, trackerClickListener);
reportBinding.trackers.setNestedScrollingEnabled(false);
reportBinding.trackers.setAdapter(trackerAdapter);
@ -151,6 +153,10 @@ public class ReportFragment extends Fragment implements Updatable {
this.packageInfo = packageInfo;
}
private void setOnTrackerClickListener(TrackerListAdapter.OnTrackerClickListener listener) {
trackerClickListener = listener;
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.action_filter);

View File

@ -0,0 +1,155 @@
package org.eu.exodus_privacy.exodusprivacy.fragments;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.text.Html;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import org.eu.exodus_privacy.exodusprivacy.R;
import org.eu.exodus_privacy.exodusprivacy.Utils;
import org.eu.exodus_privacy.exodusprivacy.adapters.ApplicationListAdapter;
import org.eu.exodus_privacy.exodusprivacy.adapters.ApplicationViewModel;
import org.eu.exodus_privacy.exodusprivacy.databinding.TrackerBinding;
import org.eu.exodus_privacy.exodusprivacy.manager.DatabaseManager;
import org.eu.exodus_privacy.exodusprivacy.objects.Tracker;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
public class TrackerFragment extends Fragment implements ComputeAppListTask.Listener, Updatable {
private TrackerBinding trackerBinding;
private long trackerId;
private PackageManager packageManager;
private List<ApplicationViewModel> applications;
private AppListFragment appListFragment;
private ApplicationListAdapter.OnAppClickListener onAppClickListener;
public static TrackerFragment newInstance(long trackerId) {
TrackerFragment fragment = new TrackerFragment();
fragment.setTrackerId(trackerId);
return fragment;
}
private void setTrackerId(long id) {
trackerId = id;
}
@Override
public void onUpdateComplete() {
Context context = trackerBinding.getRoot().getContext();
Tracker tracker = DatabaseManager.getInstance(context).getTracker(trackerId);
trackerBinding.name.setText(tracker.name);
trackerBinding.codeDetection.setText(tracker.codeSignature);
trackerBinding.networkDetection.setText(tracker.networkSignature);
trackerBinding.description.setText(Html.fromHtml(Utils.markdownToHtml(tracker.description)));
trackerBinding.description.setMovementMethod(LinkMovementMethod.getInstance());
trackerBinding.description.setClickable(true);
trackerBinding.trackerUrl.setOnClickListener(v -> {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(tracker.website));
startActivity(intent);
});
displayAppListAsync();
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
trackerBinding = DataBindingUtil.inflate(inflater, R.layout.tracker,container,false);
if (applications == null)
applications = new ArrayList<>();
appListFragment = new AppListFragment();
appListFragment.setFilter(AppListFragment.Type.TRACKER,trackerId);
appListFragment.disableScrollBar();
appListFragment.setOnAppClickListener(onAppClickListener);
FragmentManager manager = getChildFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.applications,appListFragment);
transaction.commit();
Context context = trackerBinding.getRoot().getContext();
packageManager = context.getPackageManager();
onUpdateComplete();
return trackerBinding.getRoot();
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem item = menu.findItem(R.id.action_filter);
item.setVisible(false);
item = menu.findItem(R.id.action_settings);
item.setVisible(false);
}
private void displayAppListAsync() {
trackerBinding.noAppFound.setVisibility(View.GONE);
trackerBinding.trackerPresence.setVisibility(View.GONE);
//todo
trackerBinding.trackerPresenceNb.setVisibility(View.GONE);
//todo
trackerBinding.trackerPresenceTitle.setVisibility(View.GONE);
if (applications.isEmpty()) {
trackerBinding.retrieveApp.setVisibility(View.VISIBLE);
}
new ComputeAppListTask(
new WeakReference<>(packageManager),
new WeakReference<>(DatabaseManager.getInstance(getActivity())),
new WeakReference<>(this)
).execute();
}
@Override
public void onAppsComputed(List<ApplicationViewModel> apps) {
this.applications = apps;
trackerBinding.retrieveApp.setVisibility(View.GONE);
trackerBinding.noAppFound.setVisibility(apps.isEmpty() ? View.VISIBLE : View.GONE);
trackerBinding.trackerPresence.setVisibility(View.VISIBLE);
trackerBinding.trackerPresenceNb.setVisibility(View.VISIBLE);
trackerBinding.trackerPresenceTitle.setVisibility(View.VISIBLE);
appListFragment.setApplications(apps);
int total = appListFragment.getTotalApps();
int displayedApps = appListFragment.getDisplayedApps();
int percent = displayedApps*100/total;
if(percent >=50)
trackerBinding.trackerPresenceNb.setBackgroundResource(R.drawable.square_red);
else if(percent >=33)
trackerBinding.trackerPresenceNb.setBackgroundResource(R.drawable.square_dark_orange);
else if(percent >=20)
trackerBinding.trackerPresenceNb.setBackgroundResource(R.drawable.square_yellow);
else
trackerBinding.trackerPresenceNb.setBackgroundResource(R.drawable.square_light_blue);
trackerBinding.trackerPresenceNb.setText(percent+"%");
Context context = trackerBinding.getRoot().getContext();
String presence = context.getResources().getString(R.string.tracker_presence,displayedApps);
trackerBinding.trackerPresence.setText(presence);
trackerBinding.trackerPresenceTitle.setText(R.string.tracker_presence_in);
}
public void setOnAppClickListener(ApplicationListAdapter.OnAppClickListener listener) {
onAppClickListener = listener;
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorDarkOrange"/>
<corners android:radius="5dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/colorLightBlue"/>
<corners android:radius="5dp"/>
<padding android:left="0dp" android:top="0dp" android:right="0dp" android:bottom="0dp" />
</shape>

View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<data>
</data>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textSize="30sp"
android:textColor="@color/colorPurple"
android:textStyle="bold"
android:textAlignment="center"/>
<TextView
android:id="@+id/tracker_presence"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="15dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/name"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="@color/textColorDark"/>
<TextView
android:id="@+id/tracker_presence_nb"
android:layout_width="40dp"
android:layout_height="0dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="20dp"
app:layout_constraintTop_toTopOf="@id/tracker_presence"
app:layout_constraintStart_toEndOf="@id/tracker_presence"
android:textColor="@color/textColorDark"
android:textStyle="bold"
android:textAlignment="center"
android:textSize="14sp"/>
<TextView
android:id="@+id/dummy"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="@id/tracker_presence"
app:layout_constraintStart_toEndOf="@id/tracker_presence_nb"
app:layout_constraintEnd_toEndOf="parent"/>
<TextView
android:id="@+id/tracker_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:autoLink="web"
android:text="@string/tracker_web_page"
app:layout_constraintEnd_toEndOf="parent"
android:textAlignment="textEnd"
app:layout_constraintTop_toBottomOf="@id/tracker_presence"
android:layout_marginTop="5dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:textSize="16sp"
android:textColor="@color/colorPurple"/>
<TextView
android:id="@+id/description"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginBottom="5dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
app:layout_constraintTop_toBottomOf="@id/tracker_url"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
<TextView
android:id="@+id/detection_rules"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/detection_rules"
android:layout_marginStart="10dp"
android:layout_marginEnd="20dp"
android:layout_marginTop="30dp"
app:layout_constraintTop_toBottomOf="@id/description"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textStyle="bold"
android:textSize="22sp"
android:textColor="@color/textColorDark"/>
<TextView
android:id="@+id/code_detection_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/code_signature"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
app:layout_constraintTop_toBottomOf="@id/detection_rules"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
<TextView
android:id="@+id/code_detection"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
app:layout_constraintTop_toBottomOf="@id/code_detection_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textColor="@color/textDetection"
/>
<TextView
android:id="@+id/network_detection_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/network_signature"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
app:layout_constraintTop_toBottomOf="@id/code_detection"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
/>
<TextView
android:id="@+id/network_detection"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
app:layout_constraintTop_toBottomOf="@id/network_detection_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textColor="@color/textDetection"
/>
<TextView
android:id="@+id/tracker_presence_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="20dp"
android:layout_marginTop="30dp"
app:layout_constraintTop_toBottomOf="@id/network_detection"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textStyle="bold"
android:textSize="22sp"
android:textColor="@color/textColorDark"/>
<TextView
android:id="@+id/no_app_found"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/no_app_found_tracker"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tracker_presence_title"
/>
<ProgressBar
android:id="@+id/retrieve_app"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tracker_presence_title"/>
<FrameLayout
android:id="@+id/applications"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tracker_presence_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</layout>

View File

@ -37,6 +37,13 @@
<string name="tracker_infos">Un pisteur est une partie du logiciel dédiée à la collecte de données sur vous et vos usages. <a href="https://reports.exodus-privacy.eu.org/fr/info/trackers/">En savoir plus…</a></string>
<string name="permission_infos">Les permissions sont les actions que l\'application peut effectuer sur votre téléphone. <a href="https://reports.exodus-privacy.eu.org/fr/info/permissions/">En savoir plus…</a></string>
<string name="permission_infos_dangerous">L\'icône <font color="red"><b>!</b></font> indique un niveau \'Dangereux\' ou \'Spécial\' d\'après les <a href="https://developer.android.com/guide/topics/permissions/overview">niveaux de protection de Google.</a></string>
<string name="tracker_web_page">Page web du pisteur ➤</string>
<string name="detection_rules">Règles de détection</string>
<string name="code_signature">Règle de détection(code):</string>
<string name="network_signature">Règle de détection(réseau):</string>
<string name="tracker_presence">Présent dans %d de vos applications</string>
<string name="tracker_presence_in">Présent dans:</string>
<string name="no_app_found_tracker">Ce pisteur ne semble pas être présent dans vos applications</string>
<!-- Menu -->
<string name="menu_action_filter">Filtrer</string>

View File

@ -3,13 +3,19 @@
<color name="colorPrimary">#684971</color>
<color name="colorPrimaryDark">#3d2b43</color>
<color name="colorAccent">#684971</color>
<color name="colorGreen">#6fc384</color>
<color name="colorRed">#e46772</color>
<color name="colorYellow">#ffdb66</color>
<color name="colorLightRed">#e46772</color>
<color name="colorLightYellow">#ffdb66</color>
<color name="colorLightBlue">#17a2b8</color>
<color name="colorYellow">#ffc70f</color>
<color name="colorDarkOrange">#ff8c00</color>
<color name="colorRed">#e61718</color>
<color name="colorPurple">#684971</color>
<color name="textColorDark">#343A40</color>
<color name="textColorDarkLight">#6C757D</color>
<color name="textColorWhite">#FFFFFF</color>
<color name="textDetection">#E83E8C</color>
</resources>

View File

@ -37,6 +37,13 @@
<string name="tracker_infos">A tracker is a piece of software meant to collect data about you or your usages. <a href="https://reports.exodus-privacy.eu.org/en/info/trackers/">Learn more…</a></string>
<string name="permission_infos">Permissions are actions the application can do on your phone. <a href="https://reports.exodus-privacy.eu.org/en/info/permissions/">Learn more…</a></string>
<string name="permission_infos_dangerous">The icon <font color="red"><b>!</b></font> indicates a \'Dangerous\' or \'Special\' level according to <a href="https://developer.android.com/guide/topics/permissions/overview">Google\'s protection levels.</a></string>
<string name="tracker_web_page">Tracker web page ➤</string>
<string name="detection_rules">Detection Rules</string>
<string name="code_signature">Code detection rule:</string>
<string name="network_signature">Network detection rule:</string>
<string name="tracker_presence">Present in %d of your applications</string>
<string name="tracker_presence_in">Present in:</string>
<string name="no_app_found_tracker">This tracker seems not be present in your applications</string>
<!-- Menu -->
<string name="menu_action_filter">Filter</string>